原图如下:
构造灰度直方图:
/*构造灰度直方图*/
void showHistoFunc()
{
//分割通道
vector bgr;
split(img, bgr);
//创建有256个子区间的直方图
int numbins = 256;
//设置范围(B,G,R),最后一个值不包含
float range[] = { 0, 256 };
const float *histRange = { range };
//计算每个直方图
Mat b_hist, g_hist, r_hist;
calcHist(&bgr[0], 1, 0, Mat(), b_hist, 1, &numbins, &histRange);
calcHist(&bgr[1], 1, 0, Mat(), g_hist, 1, &numbins, &histRange);
calcHist(&bgr[2], 1, 0, Mat(), r_hist, 1, &numbins, &histRange);
//绘制直方图
int width = 512;
int height = 300;
Mat histImage(height, width, CV_8UC3, Scalar(20,20,20)); //以灰色为基底创建图像
//从0到图像的高度归一化直方图
normalize(b_hist, b_hist, 0, height, NORM_MINMAX);
normalize(g_hist, g_hist, 0, height, NORM_MINMAX);
normalize(r_hist, r_hist, 0, height, NORM_MINMAX);
int binStep = cvRound((float)width/(float)numbins);
for (int i = 1; i < numbins; i++)
{
line(histImage, Point(binStep*(i - 1), height - cvRound(b_hist.at(i - 1))), Point(binStep*(i), height - cvRound(b_hist.at(i))), Scalar(255, 0, 0));
line(histImage, Point(binStep*(i - 1), height - cvRound(g_hist.at(i - 1))), Point(binStep*(i), height - cvRound(g_hist.at(i))), Scalar(0, 255, 0));
line(histImage, Point(binStep*(i - 1), height - cvRound(r_hist.at(i - 1))), Point(binStep*(i), height - cvRound(r_hist.at(i))), Scalar(0, 0, 255));
}
imshow("Histogram", histImage);
}
效果:
图像色彩均衡化(增强了对比度):
/*图像色彩均衡化:只需要均衡亮度通道(即Y通道)*/
void equalizeFunc()
{
Mat result;
//BGR图像转化为YCbCr
Mat ycrcb;
cvtColor(img, ycrcb, COLOR_BGR2YCrCb);
//图像通道分离
vector channels;
split(ycrcb, channels);
//只均衡y通道
equalizeHist(channels[0], channels[0]);
//合并结果通道
merge(channels, ycrcb);
//将YCrCB转为BGR格式
cvtColor(ycrcb, result, COLOR_YCrCb2BGR);
imshow("Equalized", result);
}
效果:
实现Lomo效果
/*Lomo效果*/
void lomoFunc()
{
Mat result;
const double exponential_e = std::exp(1.0);
//建立一个包含256个元素的映射表
Mat lut(1, 256, CV_8UC1);
for (int i = 0; i < 256; i++)
{
float x = (float)i / 256.0;
lut.at(i) = cvRound(256 * (1 / (1 + pow(exponential_e, -((x - 0.5) / 0.1)))));
}
//拆分图像通道,并只给红色通道应用值变换
vector bgr;
split(img, bgr);
LUT(bgr[2], lut, bgr[2]);
//合并结果
merge(bgr, result);
//创建晕暗的图像
Mat halo(img.rows, img.cols, CV_32FC3, Scalar(0.3, 0.3, 0.3));
//创建圆
circle(halo, Point(img.cols / 2, img.rows / 2), img.cols / 3, Scalar(1, 1, 1), -1);
blur(halo, halo, Size(img.cols / 3, img.cols / 3));
//将结果转化为浮点型
Mat resultf;
result.convertTo(resultf, CV_32FC3);
//将结果和halo相乘
multiply(resultf, halo, resultf);
//转化为8位图像
resultf.convertTo(result, CV_8UC3);
imshow("Lomograpy", result);
}
效果:
实现卡通效果:
/* 卡通效果 */
void cartoonFunc()
{
//------edges---------//
//用中值滤波去除噪声
Mat imgMedian;
medianBlur(img, imgMedian, 7);
//边缘检测
Mat imgCanny;
Canny(imgMedian, imgCanny, 50, 150);
//边缘膨胀
Mat kernel = getStructuringElement(MORPH_RECT, Size(2, 2));
dilate(imgCanny, imgCanny, kernel);
//边缘值缩放到1, 并将值翻转
imgCanny = imgCanny / 255;
imgCanny = 1 - imgCanny;
//使用浮点值(允许在0和1之间相乘)
Mat imgCannyf;
imgCanny.convertTo(imgCannyf, CV_32FC3);
//模糊边缘(实现平滑效果)
blur(imgCannyf, imgCannyf, Size(5, 5));
//------color---------//
//色彩均匀化(使用双边滤波器)
Mat imgBF;
bilateralFilter(img, imgBF, 9, 150.0, 150.0);
//截断颜色
Mat result = imgBF / 25;
result = result * 25;
//------Merge color+edges---------//
//为边缘创建3个通道
Mat imgCanny3c;
Mat cannyChannels[] = { imgCannyf, imgCannyf, imgCannyf };
merge(cannyChannels, 3, imgCanny3c);
//将结果转化为浮点型
Mat resultf;
result.convertTo(resultf, CV_32FC3);
//颜色和边缘矩阵相乘
multiply(resultf, imgCanny3c, resultf);
//转化位8位图像
resultf.convertTo(result, CV_8UC3);
imshow("cartoon", result);
}
效果: