【OpenCV】实例精解-直方图与滤波器

原图如下:

【OpenCV】实例精解-直方图与滤波器_第1张图片

构造灰度直方图:

/*构造灰度直方图*/
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);
}

效果:

【OpenCV】实例精解-直方图与滤波器_第2张图片

图像色彩均衡化(增强了对比度):

/*图像色彩均衡化:只需要均衡亮度通道(即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);
}

效果:

【OpenCV】实例精解-直方图与滤波器_第3张图片

实现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);
}

效果:

【OpenCV】实例精解-直方图与滤波器_第4张图片

实现卡通效果:

/* 卡通效果 */
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);
}

效果:

【OpenCV】实例精解-直方图与滤波器_第5张图片

你可能感兴趣的:(OpenCV,图像处理)