您的位置:首页 > 运维架构

opencv初探(二)——直方图均衡化与双线性插值缩放

2016-01-03 18:25 537 查看
这两种算法均基于上一篇所提到的图像像素遍历,通过对每个像素进行相应操作,达到总体上的目的。

一、直方图均衡化

直方图均衡化是增强图像对比度的有效方法。通过对各像素频率的统计来重新分配该像素对应的新像素,但要保证像素之间的大小关系不能翻转,是以采取累积频率来分配像素。

void equalHist(Mat inputImage, Mat &outputImage)
{
int rowNumber = inputImage.rows;
int colNumber = inputImage.cols;
int total = rowNumber*colNumber;
outputImage = Mat(rowNumber, colNumber, CV_8UC1);
int freq[256] = { 0 };//各像素出现次数

for (int i = 0; i < rowNumber; i++)
{
uchar *pixel_adress = inputImage.ptr<uchar>(i);
uchar *pixel_adress2 = outputImage.ptr<uchar>(i);
for (int j = 0; j < colNumber; j++)
{
freq[int(pixel_adress[j])] += 1;//对应次数+1
//cout << "pixel: " << int(pixel_adress[j]) << endl;
}

}
double freq2[256] = { 0 };//各像素出现频率累积,从0到255
freq2[0] = double(freq[0]) / total;
//cout <<"freq[255]:"<<freq[255]<< " freq[0]:" << freq[0] << " freq2[0]:" << freq2[0] << endl;
for (int j = 1; j < 256; j++)
{
freq2[j] = freq2[j - 1] + double(freq[j]) / total;
}
//cout <<"freq2[255]:"<<freq2[255]<< " freq2[0]:" << freq2[0] << " freq2[0]:" << freq2[0] << endl;
uchar pixel[256] = { 0 };//各像素根据累积频率对应的新像素
for (int k = 0; k < 256; k++)
{
pixel[k] = uchar(freq2[k] * 256);
}

for (int i = 0; i < rowNumber; i++)
{
uchar *in_pixel = inputImage.ptr<uchar>(i);
uchar *out_pixel = outputImage.ptr<uchar>(i);
for (int j = 0; j < colNumber; j++)
{
out_pixel[j] = pixel[int(in_pixel[j])];
}
}
imshow("out_pixel", outputImage);
imwrite("out_pixel.jpg", outputImage);
}


二、双线性插值图片缩放

图片缩放有多种不同的算法,可根据目的相应的选择。双线性插值法比较简单而且效果也不错。该算法中根据缩放比例,从原图的像素中进行抽样组成新图像的像素。其中需要重点注意整数小数之间的转换以及像素之间对应的位置关系。

void myResize( Mat inputImage, Mat &outputImage, const double onRows ,const double onCols)
{//双线性插值法缩放图片
int rowNum = int(inputImage.rows*onRows);
int colNum = int(inputImage.cols*onCols);
outputImage = Mat(rowNum, colNum,inputImage.type());
for (int i = 0; i < rowNum; i++)
{
double cof[6] = { 0 };
double sampleRow = (double(i))/onRows;
uchar *pixel_adress2 = outputImage.ptr<uchar>(i);//目的像素行首地址
for (int j = 0; j < colNum; j++)
{
double sampleCol = (double(j)) / onCols;
uchar *pixel_adress = inputImage.ptr<uchar>(int(sampleRow));//源像素行首地址
uchar *pixel_adress3;
if ((int(sampleRow) + 1) == rowNum)
{
pixel_adress3 = inputImage.ptr<uchar>(int(sampleRow) - 1);
}
else  pixel_adress3 = inputImage.ptr<uchar>(int(sampleRow) + 1);//下一行源像素行首地址
//cout << int(sampleRow) + 1 << " rowNum: " << rowNum << endl;

cof[4] = sampleRow - (int)sampleRow;//t
cof[5] = sampleCol - (int)sampleCol;//u
cof[0] = (1 - cof[4])*(1 - cof[5]);//(1-t)*(1-u)
cof[1] = cof[4] * (1 - cof[5]);//t*(1-u)
cof[2] = (1 - cof[4])*cof[5];//(1-t)*u
cof[3] = cof[4] * cof[5];//t*u
for (int k = 0; k<outputImage.channels(); k++)//对每个像素进行操作
{
pixel_adress2[j*3+k] = cof[0] * pixel_adress[int(sampleCol)*3+k] + cof[1] * pixel_adress[int(sampleCol)*3 + k] +
cof[2] * pixel_adress3[int(sampleCol)*3+k] + cof[3] * pixel_adress3[int(sampleCol)*3 + k];
//pixel_adress2[j] = uchar(cof[0] * inputImage.at<uchar>((int)sampleRow, (int)sampleCol)) + cof[1] * inputImage.at<uchar>((int)sampleRow, (int)sampleCol  + 1)
//+ cof[2] * inputImage.at<uchar>((int)sampleRow + 1, (int)sampleCol ) + cof[3] * inputImage.at<uchar>((int)sampleRow + 1, (int)sampleCol  + 1);
pixel_adress2[j] > 256 ? 256 : pixel_adress2[j];//防止像素大小超出范围
pixel_adress2[j] < 0 ? 0 : pixel_adress2[j];
}
}
}
imwrite("output.jpg", outputImage);
imshow("output", outputImage);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息