opoencv直接提供了equalizeHist(src, dst); 来均衡化处理,很多图像处理的书本介绍均衡化的都差不多,最后归结到一个对于离散灰度级的转换公式。参考书本《数字图像处理与机器视觉》的P90-91.
该书下载地址:http://pan.baidu.com/share/link?shareid=3551301329&uk=1610854122
效果跟直接使用函数式一样的。
但是我的水平有限,使用的方法比opencv直接提供的方法慢很多。请给菜鸟提宝贵建议。
修改上面的for循环,使用ptr函数。但是时间居然比at长,好郁闷啊。
Mat Hist_equalize(Mat &image)
{
Mat inputimage;
inputimage = image;
cvtColor(inputimage, inputimage, CV_BGR2GRAY);//灰度化
int Area = inputimage.rows * inputimage.cols;//计算总像素
int Dmax = 255;
int histSize = 256;//设置bin数目
float range[] = {0, 255};//设定取值范围
const float* histRange = { range };
bool uniform = true;
bool accumulate = false;
Mat output_hist;//存储直方图矩阵
///计算直方图
//rgb_planes[]输入的通道数
//1:输入数组的个数
//0:需要统计的通道(dim)索引,统计灰度,写0就可以了
//Mat():掩码(0表示忽略该像素),如果未定义,则不适用掩码
//output_hist:存储直方图的矩阵
//1:直方图维数
//histSize:每个维度的bin数目
//histrange:每个维度的取值范围
//uniform和accumulate:bin大小相同,清楚直方图痕迹
calcHist(&inputimage, 1, 0, Mat(), output_hist, 1, &histSize, &histRange, uniform, accumulate);
inputimage.convertTo(inputimage, CV_64FC1, 1, 0);
output_hist.convertTo(output_hist, CV_64FC1, 1, 0);
double tempDB;//转换后的灰度值
for (int i = 0; i < 512; i++)
{
for (int j = 0; j < 512; j++)
{
int gray_before = (int)inputimage.at<double>(i,j);//转换前的灰度值
tempDB = 0;//累加器清零
for (int k = 0; k <= gray_before; k++)
{
tempDB += output_hist.at<double>(k,0);//灰度均衡转换
}
inputimage.at<double>(i,j) = tempDB*Dmax/Area;
}
}
inputimage.convertTo(inputimage, CV_8UC1, 1, 0);
return inputimage;
}
改造的for循环:
for (int i = 0; i < 512; i++)
{
double* datain = inputimage.ptr<double>(i);
for (int j = 0; j < 512; j++)
{
int gray_before = (int)datain[j];//(int)inputimage.at<double>(i,j);//转换前的灰度值
tempDB = 0;//累加器清零
for (int k = 0; k <= gray_before; k++)
{
double* dataout = output_hist.ptr<double>(k);
tempDB +=dataout[0];
//tempDB += output_hist.at<double>(k,0);//灰度均衡转换
}
//inputimage.at<double>(i,j) = tempDB*Dmax/Area;
datain[j] = tempDB*Dmax/Area;
}
}