最近在复习图像算法,对于一些简单的图像算法进行一个代码实现,由于找工作比较忙,具体原理后期补上,先上代码。今天先给出直方图均衡化和直方图规定化(匹配)。
1.直方图均衡化
针对整个图像偏较暗色调,对图像进行全局拉伸,增强图像质量。
(1)步骤:
(a)计算每个像素值的频数Hist
(b)计算每个像素值的频率(直方图)HistP = Hist/像素个数N
(c)计算累计直方图HistPSum
(d)求直方图均衡化之后的像素值255*HistPSum
(2)代码
# include
# include
using namespace cv;
using namespace std;
Mat HistEq(Mat &srcImage);
Mat rgbTOgray(Mat srcImg);
int main()
{
Mat srcImg = imread("D:\\Visual Studio 2015\\Girl.bmp");
Mat resultImg;
if (!srcImg.data)
{
cout << "图片不存在" << endl;
}
if (srcImg.channels() == 3)
{
Mat gray = rgbTOgray(srcImg);
resultImg = HistEq(gray);
imshow("gray", gray);
imshow("result", resultImg);
}
if (srcImg.channels() == 1)
{
resultImg = HistEq(srcImg);
imshow("gray", srcImg);
imshow("result", resultImg);
}
waitKey(0);
return 0;
}
//彩色转灰度
Mat rgbTOgray(Mat srcImg)
{
int rows = srcImg.rows;
int cols = srcImg.cols;
Mat gray(rows, cols, CV_8UC1);
int i, j;
for (i = 0; i < rows; i++)
{
for (j = 0; j < cols; j++)
{
gray.at(i, j) = (int)(0.114*srcImg.at(i, j)[0] + 0.587*srcImg.at(i, j)[1] + 0.299*srcImg.at(i, j)[2]);
}
}
return gray;
}
//直方图均衡化
Mat HistEq(Mat &srcImage)
{
int rows = srcImage.rows;
int cols = srcImage.cols;
Mat resultImage(rows, cols, srcImage.type());
int Hist[256];
double HistP[256];
double HistPSum[256];
int EqHist[256];
int i, j;
for (i = 0; i < 256; i++)
{
Hist[i] = 0;
HistP[i] = 0.0;
HistPSum[i] = 0.0;
EqHist[i] = 0;
}
//求每个像素的频数
for (i = 0; i < rows; i++)
{
for (j = 0; j < cols; j++)
{
Hist[(int)srcImage.at(i, j)]++;
}
}
//每个像素的概率
for (i = 0; i < 256; i++)
{
HistP[i] = (double)Hist[i] / (rows*cols);
}
//每个像素的累计概率
HistPSum[0] = HistP[0];
for (i = 1; i < 256; i++)
{
HistPSum[i] = HistP[i] + HistPSum[i - 1];
}
//直方图均衡化之后的值
for (i = 0; i < 256; i++)
{
EqHist[i] = cvRound((double)HistPSum[i] * 255);
}
for (i = 0; i < rows; i++)
{
for (j = 0; j < cols; j++)
{
resultImage.at(i, j) = EqHist[(int)srcImage.at(i, j)];
}
}
return resultImage;
}
(3)结果
2.直方图规定化(匹配)
直方图均衡化针对全局进行拉伸,不能满足特定某一段直方图修正的作用,于是使用直方图规定化。
(1)步骤:
(a)计算原始图像和目标图像的每个像素值的频数Hist
(b)计算原始图像和目标图像的每个像素值的频率(直方图)HistP = Hist/像素个数N
(c)计算原始图像和目标图像的累计直方图HistPSum
(d)计算原始图像和目标图像的累计直方图的差的最小值作作为映射规则
(2)代码
# include
# include
# include
using namespace cv;
using namespace std;
Mat HistMatch(Mat &srcImage, Mat &targetImage);
Mat rgbTOgray(Mat srcImg);
int main()
{
Mat srcImg = imread("D:\\Visual Studio 2015\\lena.bmp");
Mat targetImg = imread("D:\\Visual Studio 2015\\Girl.bmp");
Mat resultImg;
if (!srcImg.data || !targetImg.data)
{
cout << "图片不存在" << endl;
}
Mat gray1 = rgbTOgray(srcImg);
Mat gray2 = rgbTOgray(targetImg);
resultImg = HistMatch(gray1, gray2);
imshow("gray1", gray1);
imshow("gray2", gray2);
imshow("result", resultImg);
waitKey(0);
return 0;
}
//彩色转灰度
Mat rgbTOgray(Mat srcImg)
{
int rows = srcImg.rows;
int cols = srcImg.cols;
Mat gray(rows, cols, CV_8UC1);
int i, j;
for (i = 0; i < rows; i++)
{
for (j = 0; j < cols; j++)
{
gray.at(i, j) = (int)(0.114*srcImg.at(i, j)[0] + 0.587*srcImg.at(i, j)[1] + 0.299*srcImg.at(i, j)[2]);
}
}
return gray;
}
//直方图规定化
Mat HistMatch(Mat &srcImage, Mat &targetImage)
{
int rows = srcImage.rows;
int cols = srcImage.cols;
int rows_t = targetImage.rows;
int cols_t = targetImage.cols;
Mat resultImage(rows, cols, srcImage.type());
int Hist[256];
double HistP[256];
double HistPSum[256];
int Hist_t[256];
double HistP_t[256];
double HistPSum_t[256];
int HistMatch[256];
int i, j;
for (i = 0; i < 256; i++)
{
Hist[i] = 0;
HistP[i] = 0.0;
HistPSum[i] = 0.0;
Hist_t[i] = 0;
HistP_t[i] = 0.0;
HistPSum_t[i] = 0.0;
HistMatch[i] = 0;
}
//求每个像素的频数
for (i = 0; i < rows; i++)
{
for (j = 0; j < cols; j++)
{
Hist[(int)srcImage.at(i, j)]++;
}
}
for (i = 0; i < rows_t; i++)
{
for (j = 0; j < cols_t; j++)
{
Hist_t[(int)targetImage.at(i, j)]++;
}
}
//每个像素的概率
for (i = 0; i < 256; i++)
{
HistP[i] = (double)Hist[i] / (rows*cols);
HistP_t[i] = (double)Hist_t[i] / (rows_t*cols_t);
}
//每个像素的累计概率
HistPSum[0] = HistP[0];
HistPSum_t[0] = HistP_t[0];
for (i = 1; i < 256; i++)
{
HistPSum[i] = HistP[i] + HistPSum[i - 1];
HistPSum_t[i] = HistP_t[i] + HistPSum_t[i - 1];
}
//求匹配度
for (i = 0; i < 256; i++)
{
double min = 255.0;
int flag = 0;
for (j = 0; j < 256; j++)
{
if (min > abs(HistPSum[i] - HistPSum_t[j]))
{
min = abs(HistPSum[i] - HistPSum_t[j]);
flag = j;
}
}
HistMatch[i] = flag;
}
for (i = 0; i < rows; i++)
{
for (j = 0; j < cols; j++)
{
resultImage.at(i, j) = HistMatch[(int)srcImage.at(i, j)];
}
}
return resultImage;
}