我正在尝试使用OpenCV使用以下函数执行直方图均衡
Mat Histogram::Equalization(const Mat& inputImage)
{
if(inputImage.channels() >= 3)
{
vector<Mat> channels;
split(inputImage,channels);
Mat B,G,R;
equalizeHist( channels[0], B );
equalizeHist( channels[1], G );
equalizeHist( channels[2], R );
vector<Mat> combined;
combined.push_back(B);
combined.push_back(G);
combined.push_back(R);
Mat result;
merge(combined,result);
return result;
}
return Mat();
}
但是当我得到结果时,输入和输出图像似乎没有区别,我做错了什么?
抱歉图像质量不好,“预处理”(左)是直方图均衡,你可以看到它与输入相同(右)。
错过了什么?
答案 0 :(得分:67)
直方图均衡是一个非线性过程。分别对每个通道进行通道分割和均衡不是对比度均衡的正确方法。均衡涉及图像的强度值而不是颜色分量。因此,对于简单的RGB彩色图像,不应在每个通道上单独应用HE。相反,应该应用它以使强度值均衡而不干扰图像的色彩平衡。因此,第一步是将图像的颜色空间从RGB转换为将颜色分量与颜色分量分开的颜色空间之一。其中一些是:
将图像从RGB转换为上述颜色空间之一。 YCbCr 是首选,因为它专为数字图像而设计。执行强度平面Y的HE。将图像转换回RGB。
在您目前的情况下,您没有观察到任何重大变化,因为图像中只有两种突出的颜色。当图像中有大量颜色时,分割方法会导致颜色不平衡。
例如,请考虑以下图像:
(注意假色)
这是使用 YCbCr 色彩空间对彩色图像进行直方图均衡的OpenCV代码。
Mat equalizeIntensity(const Mat& inputImage)
{
if(inputImage.channels() >= 3)
{
Mat ycrcb;
cvtColor(inputImage,ycrcb,CV_BGR2YCrCb);
vector<Mat> channels;
split(ycrcb,channels);
equalizeHist(channels[0], channels[0]);
Mat result;
merge(channels,ycrcb);
cvtColor(ycrcb,result,CV_YCrCb2BGR);
return result;
}
return Mat();
}
答案 1 :(得分:7)
和python版本,@ ss:
import cv2
import os
def hisEqulColor(img):
ycrcb=cv2.cvtColor(img,cv2.COLOR_BGR2YCR_CB)
channels=cv2.split(ycrcb)
print len(channels)
cv2.equalizeHist(channels[0],channels[0])
cv2.merge(channels,ycrcb)
cv2.cvtColor(ycrcb,cv2.COLOR_YCR_CB2BGR,img)
return img
fname='./your.jpg'
img=cv2.imread(fname)
cv2.imshow('img', img)
img2=hisEqulColor(img)
cv2.imshow('img2',img2)
答案 2 :(得分:1)
我为BGRA图像实现了直方图均衡。我认为这个功能对你的目标很有用(但你应该忽略alpha通道)。
Mat equalizeBGRA(const Mat& img)
{
Mat res(img.size(), img.type());
Mat imgB(img.size(), CV_8UC1);
Mat imgG(img.size(), CV_8UC1);
Mat imgR(img.size(), CV_8UC1);
Vec4b pixel;
if (img.channels() != 4)
{
cout << "ERROR: image input is not a BGRA image!" << endl;
return Mat();
}
for (int r = 0; r < img.rows; r++)
{
for (int c = 0; c < img.cols; c++)
{
pixel = img.at<Vec4b>(r, c);
imgB.at<uchar>(r, c) = pixel[0];
imgG.at<uchar>(r, c) = pixel[1];
imgR.at<uchar>(r, c) = pixel[2];
}
}
equalizeHist(imgB, imgB);
equalizeHist(imgG, imgG);
equalizeHist(imgR, imgR);
for (int r = 0; r < img.rows; r++)
{
for (int c = 0; c < img.cols; c++)
{
pixel = Vec4b(imgB.at<uchar>(r, c), imgG.at<uchar>(r, c), imgR.at<uchar>(r, c), img.at<Vec4b>(r, c)[3]);
res.at<Vec4b>(r, c) = pixel;
}
}
return res;
}