opencv直方图拉伸

时间:2022-06-16 16:23:48

1、首先计算出一幅图像的直方图

//计算直方图
cv::MatND ImageHist::getHist(const cv::Mat &image){ cv::Mat im;
if(image.channels() == 3)
cv::cvtColor(image,im,CV_RGB2GRAY,0);
else
im = image;
float r[2];
r[0] = 0;
r[1] = 255;
const float *ranges[1];
ranges[0] = r;
cv::calcHist(&im,
1,
&channels,
cv::Mat(),
hist,
1,
&histSize,
ranges);
return hist;
} //将直方图生成图像,以便在MFC空间中显示
cv::Mat ImageHist::getHistImage(const cv::Mat &image){ double maxVal = 0;
double minVal = 0;
cv::minMaxLoc(hist,&minVal,&maxVal,0,0);
cv::Mat histImg(histSize,histSize,CV_8U,cv::Scalar(255)); int high = histSize * 0.9;
for (int i = 0;i < histSize;++i)
{
float binVal = hist.at<float>(i);
int inted = binVal / maxVal *high;
cv::line(histImg,
cv::Point(i,histSize),
cv::Point(i,histSize - inted),
cv::Scalar::all(0));
}
return histImg;
}

2、去掉直方图两端bin为0或者小于某一数量的bin并记录去掉后两端的灰度值(mini,maxi),然后利用以下公式对颜色查找表进行拉伸:

(i - mini) * 255 / (maxi - mini) + 0.5
cv::Mat ImageHist::stretch(const cv::Mat &image,int minValue /* = 0 */){
int mini = 0;
for (;mini < histSize;++mini)
{
if(hist.at<float>(mini) > minValue)
break;
}
int maxi = histSize - 1;
for (;maxi >= 0;--maxi)
{
if(hist.at<float>(maxi) > minValue)
break;
} cv::Mat lookup(1,256,CV_8U);
for (int i = 0;i < histSize;++i)
{
if(i < mini)
lookup.at<uchar>(i) = 0;
else if(i > maxi)
lookup.at<uchar>(i) = 255;
else
lookup.at<uchar>(i) =static_cast<uchar>((i - mini) * 255 / (maxi - mini) + 0.5);
}
cv::Mat result;
cv::LUT(image,lookup,result);
return result;
}

结果:opencv直方图拉伸