OpenCV对视频的处理操作

官方在线帮助文档:OpenCV: OpenCV modules

1. 视频文件摄像头使用

VideoCapture capture("mv.mp4");// 0 是读取摄像头

	#include<opencv2/opencv.hpp>
	#include<iostream>
	#include<vector>
	
	using namespace cv;
	using namespace std;
	class demo
	{
	public:
		// 图像色彩空间转换
		void colorSpace_Demo(Mat& image)
		{
			Mat gray, hsv;
			cvtColor(image, hsv, COLOR_BGR2HSV);
			cvtColor(image, gray, COLOR_BGR2GRAY);
			imshow("HSV", hsv);
			imshow("灰度", gray);
			//imwrite("hsv.png", hsv);
			//imwrite("gray.png", gray);
		}
		// 视频操作
		// 视频文件摄像头使用
		void video_demo(Mat& image)
		{
			VideoCapture capture("mv.mp4");// 0 是读取摄像头
			Mat frame;
			while (true) {
				capture.read(frame);
				
				if (frame.empty()) {// 检测是否检测到人
					break;
				}
				imshow("frame", frame);
				// 读取了灰度的视频和HSV的视频
				colorSpace_Demo(frame);
				//flip(frame, frame, 1);// 翻转
				// 做事情
				int c = waitKey(10);
				if (c == 27) {
					break;
				}
			}
	
			// release
			capture.release();
		}
	};
	int main(int argc, char** argv)
	{
		Mat src = imread("迪丽热巴.png",IMREAD_UNCHANGED);
		// Mat是一种特殊的数据类型格式,是一种二维数组,用来存储图片的数据
		// namedWindow("输出窗口", WINDOW_FREERATIO);
		// 只有imshow无法调整图片显示窗口的大小,通过namedWindow调整窗口的大小
		if (src.empty()) {
			cout << "没有找到你的图片" << endl;
			return -1;
		}
	
		imshow("输出窗口", src);
	
		demo d;
		d.video_demo(src); 
		waitKey(0);// 设置图片显示时间
		destroyAllWindows();// 释放所有窗口
		return 0;
	}

2. 视频处理与保存

  • SD 标清
  • HD  高清
  • UHD  超清

写入的还是原视频,上限是2g。

	#include<opencv2/opencv.hpp>
	#include<iostream>
	#include<vector>
	
	using namespace cv;
	using namespace std;
	class demo
	{
	public:
		// 图像色彩空间转换
		void colorSpace_Demo(Mat& image)
		{
			Mat gray, hsv;
			cvtColor(image, hsv, COLOR_BGR2HSV);
			cvtColor(image, gray, COLOR_BGR2GRAY);
			imshow("HSV", hsv);
			imshow("灰度", gray);
			//imwrite("hsv.png", hsv);
			//imwrite("gray.png", gray);
		}
		// 视频操作
		// 视频文件摄像头使用
		// 视频处理与保存
		void video_demo(Mat& image)
		{
		VideoCapture capture("mv.mp4");// 0 是读取摄像头
		Mat frame;
		int frame_width = capture.get(CAP_PROP_FRAME_WIDTH);
		int frame_height = capture.get(CAP_PROP_FRAME_HEIGHT);
		int count = capture.get(CAP_PROP_FRAME_COUNT);// 帧数
		int fps = capture.get(CAP_PROP_FPS);
		cout << "frame-width:" << frame_width << endl;
		cout << "frame-height:" << frame_height << endl;
		cout << "FPS:" << fps << endl;
		cout << "Number of Frames:" << count << endl;
		VideoWriter writer("D:/桌面/test.mp4", capture.get(CAP_PROP_FOURCC), fps, Size(frame_width, frame_height), true);
		while (true) {
			capture.read(frame);
			
			if (frame.empty()) {// 检测是否检测到人
				break;
			}
			imshow("frame", frame);
			// 读取了灰度的视频和HSV的视频
			colorSpace_Demo(frame);
			writer.write(frame);
			//flip(frame, frame, 1);// 翻转
			// 做事情
			int c = waitKey(10);
			if (c == 27) {
				break;
			}
		}

		// release
		capture.release();
		writer.release();
	}
};
int main(int argc, char** argv)
{
	Mat src = imread("迪丽热巴.png",IMREAD_UNCHANGED);
	// Mat是一种特殊的数据类型格式,是一种二维数组,用来存储图片的数据
	// namedWindow("输出窗口", WINDOW_FREERATIO);
	// 只有imshow无法调整图片显示窗口的大小,通过namedWindow调整窗口的大小
	if (src.empty()) {
		cout << "没有找到你的图片" << endl;
		return -1;
	}

	imshow("输出窗口", src);

	demo d;
	d.video_demo(src); 
	waitKey(0);// 设置图片显示时间
	destroyAllWindows();// 释放所有窗口
	return 0;
}

从头开始的所有代码

#include<opencv2/opencv.hpp>
#include<iostream>
#include<vector>

using namespace cv;
using namespace std;

// 鼠标响应
Point sp(-1, -1);
Point ep(-1, -1);
// 设置一个临时图层,确保显示最后一个图片
Mat temp;
class demo
{
public:
	// 图像色彩空间转换
	void colorSpace_Demo(Mat& image)
	{
		Mat gray, hsv;
		cvtColor(image, hsv, COLOR_BGR2HSV);
		cvtColor(image, gray, COLOR_BGR2GRAY);
		imshow("HSV", hsv);
		imshow("灰度", gray);
		//imwrite("hsv.png", hsv);
		//imwrite("gray.png", gray);
	}
	// 图像对象的创建与赋值
	void mat_creation_demo(Mat& image)
	{
		Mat m1, m2;
		m1 = image.clone();
		image.copyTo(m2);

		// 创建空白图像
		Mat m3 = Mat::zeros(Size(400, 400), CV_8UC3);
		// 8位无符号字符1个通道的数据,改成3之后在表示像素点的时候的像素值都有三个,表示有三个通道
		m3 = 127;// 只赋值一个值的时候默认是第一个通道
		m3 = Scalar(127, 12, 260);// 当确定了通道数量后可以给每个通道赋值

		cout << "width:" << m3.cols << "\t height:" << m3.rows << "\tchannels:(通道)" << m3.channels() << endl;
		cout << m3 << endl;
		imshow("自定义图像", m3);

		Mat m4 = m3.clone();
		m4 = Scalar(260, 12, 127);
		imshow("自定义图像", m3);
		// m4是与m3指向同一片地址,改变m4同时会改变m3
		imshow("自定义图像4", m4);
	}
	// 图像像素的读写操作
	void pixel_visit_demo(Mat &image)
	{
		int width = image.cols;
		int height = image.rows;
		int dims = image.channels();
		for (int row = 0; row < height; row++) {
			for (int col = 0; col < width; col++) {
				if (dims == 1) {// 灰度图像
					int pv = image.at<uchar>(row, col);
					image.at<uchar>(row, col) = 255 - pv;
				}
				if (dims == 3) {// 彩色图像
					Vec3b bgr = image.at<Vec3b>(row, col);
					image.at<Vec3b>(row, col)[0] = 255 - bgr[0];
					image.at<Vec3b>(row, col)[1] = 255 - bgr[1];
					image.at<Vec3b>(row, col)[2] = 255 - bgr[2];
				}
			}
		}
		// 指针
		/*
		for (int row = 0; row < height; row++) {
			uchar* current_row = image.ptr<uchar>(row);
			for (int col = 0; col < width; col++) {
				if (dims == 1) {// 灰度图像
					int pv = *current_row;
					*current_row++ = 255 - pv;
				}
				if (dims == 3) {// 彩色图像
					*current_row++ = 255 - *current_row;
					*current_row++ = 255 - *current_row;
					*current_row++ = 255 - *current_row;
				}
			}
		}
		*/
		imshow("像素读写演示", image);
	}
	// 图像像素的算术操作
	void operatos_demo(Mat& image)
	{
		Mat dst = Mat::zeros(image.size(), image.type());
		Mat m = Mat::zeros(image.size(), image.type());
		m = Scalar(50, 50, 50);
		add(image, m, dst);
		imshow("加法操作", dst);
		subtract(image, m, dst);
		imshow("减法操作", dst);
		multiply(image, m, dst);
		imshow("乘法操作", dst);
		divide(image, m, dst);
		imshow("除法操作", dst);
	}

	// 亮度调整与对比度调整
	static void on_lightness(int b, void* userdata) {
		Mat image = *((Mat*)userdata);
		Mat dst = Mat::zeros(image.size(), image.type());
		Mat m = Mat::zeros(image.size(), image.type());
		addWeighted(image, 1.0, m, 0, b, dst);
		imshow("亮度与对比度调整", dst);
	}
	static void on_contrast(int b, void* userdata) {
		Mat image = *((Mat*)userdata);
		Mat dst = Mat::zeros(image.size(), image.type());
		Mat m = Mat::zeros(image.size(), image.type());
		double contrast = b / 100.0;
		addWeighted(image, contrast, m, 0.0, 0, dst);
		imshow("亮度与对比度调整", dst);
	}
	void tracking_bar_demo(Mat &image)
	{
		namedWindow("亮度与对比度调整", WINDOW_AUTOSIZE);
		int max_value = 100;
		int lightness = 50;
		int contract_value = 100;
		createTrackbar("Value Bar:", "亮度与对比度调整", &lightness, max_value, on_lightness,(void*)(&image));
		createTrackbar("Contrast Bar:", "亮度与对比度调整", &contract_value, 200, on_contrast, (void*)(&image));
		on_lightness(50, &image);
	}

	// 键盘响应操作
	void key_demo(Mat& image)
	{
		Mat dst = Mat::zeros(image.size(), image.type());
		while (true) {
			int c = waitKey(100);
			if (c == 27) {// 退出
				break;
			}
			if (c == 49) {// Key #1
				cout << "你按了1:要进行转换灰度的操作"<< endl;
				cvtColor(image, dst, COLOR_BGR2GRAY);
			}
			if (c == 50) {// Key  #2
				cout << "你按了2:要进行转换HSV的操作" << endl;
				cvtColor(image, dst, COLOR_BGR2HSV);
			}
			if (c == 51) {// Key  #3
				cout << "你按了3:要进行亮度的调节" << endl;
				dst = Scalar(50, 50, 50);
				add(image, dst, dst);
			}
			imshow("键盘响应", dst);
		}
	}
	// 自带颜色操作
	void color_style_demo(Mat &image)
	{
		int colormap[] = {
			COLORMAP_AUTUMN,
			COLORMAP_BONE,
			COLORMAP_JET,
			COLORMAP_WINTER,
			COLORMAP_RAINBOW,
			COLORMAP_OCEAN,
			COLORMAP_SUMMER,
			COLORMAP_SPRING,
			COLORMAP_COOL,
			COLORMAP_PINK,
			COLORMAP_HOT,
			COLORMAP_PARULA,
			COLORMAP_MAGMA,
			COLORMAP_INFERNO,
			COLORMAP_PLASMA,
			COLORMAP_VIRIDIS,
			COLORMAP_CIVIDIS,
			COLORMAP_TWILIGHT,
			COLORMAP_TWILIGHT_SHIFTED
		};
		Mat dst;
		int index = 0;
		while (true) {
			int c = waitKey(1000);
			if (c == 27) {// 退出
				break;
			}
			applyColorMap(image, dst, colormap[index%19]);
			index++;
			imshow("颜色风格", dst);
		}
	}
	// 图像像素的逻辑操作
	void bitwise_demo(Mat& image)
	{
		Mat m1 = Mat::zeros(Size(256, 256), CV_8UC3);
		Mat m2 = Mat::zeros(Size(256, 256), CV_8UC3);
		rectangle(m1, Rect(100, 100, 80, 80), Scalar(255, 255, 0), -1, LINE_8, 0);
		// -1 是填充,2是描边
		rectangle(m2, Rect(150, 150, 80, 80), Scalar(0, 255, 255), -1, LINE_8, 0);
		imshow("m1", m1);
		imshow("m2", m2);
		Mat dst;
		bitwise_and(m1, m2, dst);
		imshow("像素与操作", dst);
		bitwise_or(m1, m2, dst);
		imshow("像素或操作", dst);
		bitwise_not(image, dst);
		// Mat dst = ~image;//取反
		imshow("取反", dst);
		bitwise_xor(m1, m2, dst);
		imshow("异或", dst);

	}
	// 通道分离与合并
	void channels_demo(Mat& image)
	{
		// 通道分离
		vector<Mat> mv;
		split(image, mv);
		imshow("蓝色", mv[0]);
		imshow("绿色", mv[1]);
		imshow("红色", mv[2]);

		Mat dst;
		mv[1] = 0;
		mv[2] = 0;
		merge(mv, dst);
		imshow("蓝色", dst);
		// 同理修改其他两种通道后彰显一种通道的颜色
		// 也可以只让其中一个通道的值为0

		// 通道的合并
		int from_to[] = { 0,2,1,1,2 };
		mixChannels(&image, 1, &dst, 1, from_to, 3);
		imshow("通道混合", dst);
	}
	// 图像色彩空间转换
	void inrange_demo(Mat& image)
	{
		Mat hsv;
		cvtColor(image, hsv, COLOR_BGR2HSV);
		Mat mask;
		inRange(hsv, Scalar(0, 43, 46), Scalar(180, 255, 255), mask);
		imshow("mask", mask);

		Mat redback = Mat::zeros(Size(), image.type());
		redback = Scalar(40, 40, 200);
		bitwise_not(mask, mask);
		imshow("mask", mask);
		image.copyTo(redback, mask);
		imshow("roi区域提取", redback);
	}
	// 图像像素值统计
	void pixel_statistic_demo(Mat& image)
	{
		double minv, maxv;
		Point minLoc, maxLoc;
		vector<Mat> mv;
		split(image, mv);
		for (int i = 0; i < mv.size(); i++)
		{
			minMaxLoc(mv[i], &minv, &maxv, &minLoc, &maxLoc, Mat());
			cout << "No.channels:" << i << "min value:" << minv << "max value:" << maxv << endl;
		}		
		Mat mean, stddev;
		meanStdDev(image, mean, stddev);
		cout << "means:" << mean << endl;
		cout<<"stddev:" << stddev << endl;
	}
	// 图像几何形状绘制
	void drawing_demo(Mat& image)
	{
		Rect rect;
		rect.x = 300;
		rect.y = 200;
		rect.width = 100;
		rect.height = 100;
		rectangle(image, rect, Scalar(0, 0, 255), 2, 8, 0);
		// 2,绘制.  -1,填充
		circle(image, Point(150, 250), 50, Scalar(255, 0, 0), 2, 8, 0);
		line(image, Point(300, 200), Point(400, 300), 2, LINE_AA, 0);
		// LINE_AA 边缘融合
		RotatedRect rrt;
		rrt.center = Point(150, 150);
		rrt.size = Size(100, 200);
		rrt.angle = 90.0;
		ellipse(image, rrt, Scalar(0, 255, 255), 2, 8);
		imshow("图像演示", image);
	}
	// 随机数与随机颜色
	void random_drawing()
	{
		Mat canvas = Mat::zeros(Size(512, 512), CV_8UC3);
		int width = canvas.cols;
		int height = canvas.rows;
		RNG rng(12345);
		while (true) {
			int c = waitKey(100);
			if (c == 27) {
				break;
			}
			// 随机坐标
			int x1 = rng.uniform(0, width);
			int y1 = rng.uniform(0, height);
			int x2 = rng.uniform(0, width);
			int y2 = rng.uniform(0, height);

			// 随机颜色
			int b = rng.uniform(0, 255);
			int g = rng.uniform(0, 255);
			int r = rng.uniform(0, 255);

			//canvas = Scalar(0, 0, 0);
			// 设置每次都只花一条直线,用黑色背景覆盖每次
			line(canvas, Point(x1, y1), Point(x2, y2), Scalar(b, g, r), 4, LINE_AA, 0);
			imshow("随机绘制演示", canvas);
		}
	}
	// 多边形填充与绘制
	void polyline_drawing_demo() 
	{
		Mat canvas = Mat::zeros(Size(512, 512), CV_8UC3);
		Point p1(100, 100);
		Point p2(350, 100);
		Point p3(450, 280);
		Point p4(320, 450);
		Point p5(80, 400);

		vector<Point> pts(5);
		pts.push_back(p1);
		pts.push_back(p2);
		pts.push_back(p3);
		pts.push_back(p4);
		pts.push_back(p5);

		// 绘制
		//polylines(canvas, pts, true, Scalar(0, 0, 255), 2, 8, 0);
		// 填充
		//fillPoly(canvas, pts, true, Scalar(255, 255, 0), 8, 0);

		vector<vector<Point>> contours;
		contours.push_back(pts);
		drawContours(canvas, contours, -1, Scalar(255, 0, 0), 2);
		// 2绘制形状,-1填充
		imshow("多边形绘制", canvas);
	}

	// 鼠标操作与响应
	static void on_draw(int event, int x, int y, int flags, void* userdata)
	{
		Mat image = *((Mat*)userdata);
		if (event == EVENT_LBUTTONDOWN) {
			sp.x = x;
			sp.y = y;			
			cout << "start point:" << sp << endl;
		}
		else if (event == EVENT_LBUTTONUP) {
			ep.x = x;
			ep.y = y;
			int dx = ep.x - sp.x;
			int dy = ep.y - sp.y;
			if (dx > 0 && dy > 0) {
				Rect box(sp.x, sp.y, dx, dy);
				temp.copyTo(image);// 解决ROI区域有颜色框的问题
				imshow("ROI区域", image(box));
				rectangle(image, box, Scalar(0, 255, 255), 2, 8, 0);
				imshow("鼠标绘制", image);
				// 每次绘制完成之后要更新数据
				sp.x = -1;
				sp.y = -1;
			}
			cout << "end point:" << ep << endl;			
		}
		else if (event == EVENT_MOUSEMOVE) {
			if (sp.x > 0 & sp.y > 0) {
				ep.x = x;
				ep.y = y;
				int dx = ep.x - sp.x;
				int dy = ep.y - sp.y;
				if (dx > 0 && dy > 0) {
					Rect box(sp.x, sp.y, dx, dy);
					temp.copyTo(image);
					rectangle(image, box, Scalar(0, 255, 255), 2, 8, 0);
					imshow("鼠标绘制", image);
					
				}
				cout << "end point:" << ep << endl;
			}
		}
	}
	void mouse_drawing_demo(Mat &image)
	{
		namedWindow("鼠标绘制", WINDOW_AUTOSIZE);
		setMouseCallback("鼠标绘制", on_draw,(void*)(&image));
		imshow("鼠标绘制", image);
		temp = image.clone();
	}

	// 图像像素类型转换归一化
	void norm_demo(Mat& image)
	{
		Mat dst;
		cout << image.type() << endl;
		image.convertTo(dst, CV_32F);
		cout << image.type() << endl;
		normalize(image, dst, 1.0, 0, NORM_MINMAX);
		cout << dst.type() << endl;
		imshow("图像数据归一化", dst);
		// CV_8UC3  转换为  CV_32FC3
	}
	// 图像放缩与插值
	void resize_demo(Mat& image)
	{
		Mat zoomin, zoomout;
		int height = image.rows;
		int width = image.cols;
		resize(image, zoomin, Size(width * 1.50, height * 1.50), 0, 0, INTER_LINEAR);
		imshow("zoomin", zoomin);// 放大
		resize(image, zoomout, Size(width / 2.0, height / 2.0), 0, 0, INTER_LINEAR);
		imshow("zoomout", zoomout);// 缩小
	}
	// 图像翻转
	void flip_demo(Mat& image)
	{
		Mat dst;
		flip(image, dst, 0);
		imshow("图像翻转(上下)", dst);// 上下翻转
		flip(image, dst, 1);
		imshow("图像翻转(左右)", dst);// 左右反转
		flip(image, dst, -1);
		imshow("旋转180度", dst);// 旋转180度
	}
	// 图像旋转
	void rotate_demo(Mat& image)
	{
		Mat dst,M;
		int width = image.cols;
		int height = image.rows;
		M = getRotationMatrix2D(Point2f(width / 2, height / 2), 45, 1.0);
		double cos = abs(M.at<double>(0, 0));
		double sin = abs(M.at<double>(0, 1));
		int new_width = cos * width + sin * height;
		int new_height = sin * width + cos * height;
		M.at<double>(0, 2) += (new_width / 2 - width / 2);
		M.at<double>(1, 2) += (new_height / 2 - height / 2);
		warpAffine(image, dst, M, Size(new_width, new_height), INTER_LINEAR, 0, Scalar(255, 255, 0));
		imshow("旋转演示", dst);
	}
	
	// 视频操作
	// 视频文件摄像头使用
	// 视频处理与保存
	void video_demo(Mat& image)
	{
		VideoCapture capture("mv.mp4");// 0 是读取摄像头
		Mat frame;
		int frame_width = capture.get(CAP_PROP_FRAME_WIDTH);
		int frame_height = capture.get(CAP_PROP_FRAME_HEIGHT);
		int count = capture.get(CAP_PROP_FRAME_COUNT);// 帧数
		int fps = capture.get(CAP_PROP_FPS);
		cout << "frame-width:" << frame_width << endl;
		cout << "frame-height:" << frame_height << endl;
		cout << "FPS:" << fps << endl;
		cout << "Number of Frames:" << count << endl;
		VideoWriter writer("D:/桌面/test.mp4", capture.get(CAP_PROP_FOURCC), fps, Size(frame_width, frame_height), true);
		while (true) {
			capture.read(frame);
			
			if (frame.empty()) {// 检测是否检测到人
				break;
			}
			imshow("frame", frame);
			// 读取了灰度的视频和HSV的视频
			colorSpace_Demo(frame);
			writer.write(frame);
			//flip(frame, frame, 1);// 翻转
			// 做事情
			int c = waitKey(10);
			if (c == 27) {
				break;
			}
		}

		// release
		capture.release();
		writer.release();
	}
	// 图像直方图
	void histogram_demo(Mat& image) {
		// 三通道分离
		vector<Mat> bgr_plane;
		split(image, bgr_plane);
		// 定义参数变量
		const int channels[1] = { 0 };
		const int bins[1] = { 256 };
		float hranges[2] = { 0,255 };
		const float* ranges[1] = { hranges };
		Mat b_hist;
		Mat g_hist;
		Mat r_hist;
		//计算Blue, Green,Red通道的直方图
		calcHist(&bgr_plane[0], 1, 0, Mat(), b_hist, 1, bins, ranges);
		calcHist(&bgr_plane[1], 1, 0, Mat(), g_hist, 1, bins, ranges);
		calcHist(&bgr_plane[2], 1, 0, Mat(), r_hist, 1, bins, ranges);

		//显示直方图
		int hist_w = 512;
		int hist_h = 400;
		int bin_w = cvRound((double)hist_w / bins[0]);
		Mat histImage = Mat::zeros(hist_h, hist_w, CV_8UC3);
		//归一化直方图数据
		normalize(b_hist, b_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat());
		normalize(g_hist, g_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat());
		normalize(r_hist, r_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat());
		// 绘制直方图曲线
		for (int i = 1; i < bins[0]; i++) {
			line(histImage, Point(bin_w * (i - 1), hist_h - cvRound(b_hist.at<float>(i - 1))),
				Point(bin_w * (i), hist_h - cvRound(b_hist.at<float>(i))), Scalar(255, 0, 0), 2, 8, 0);
			line(histImage, Point(bin_w * (i - 1), hist_h - cvRound(g_hist.at<float>(i - 1))),
				Point(bin_w * (i), hist_h - cvRound(g_hist.at<float>(i))), Scalar(0, 255, 0), 2, 8, 0);
			line(histImage, Point(bin_w * (i - 1), hist_h - cvRound(r_hist.at<float>(i - 1))),
				Point(bin_w * (i), hist_h - cvRound(r_hist.at<float>(i))), Scalar(0, 0, 255), 2, 8, 0);
		}
		// 显示直方图
		namedWindow("Histogram Demo", WINDOW_AUTOSIZE);
		imshow("Histogram Deno", histImage);
	}
	// 二维直方图
	void histogram_2d_demo(Mat& image)
	{
		// 2D直方图
		Mat hsv, hs_hist;
		cvtColor(image, hsv, COLOR_BGR2HSV); 
		int hbins = 30, sbins = 32;
		int hist_bins[] = { hbins, sbins }; 
		float h_range[] = { 0,180 };
		float s_range[] = { 0,256 };
		const float* hs_ranges[] = { h_range, s_range }; 
		int hs_channels[] = { 0,1 };
		calcHist(&hsv,1, hs_channels,Mat(), hs_hist,2, hist_bins, hs_ranges, true, false); 
		double maxval = 0;
		minMaxLoc(hs_hist, 0, &maxval, 0, 0); 
		int scale = 10;
		Mat hist2d_image = Mat::zeros(sbins * scale, hbins * scale, CV_8UC3); 
		for (int h = 0; h < hbins; h++) {
			for (int s = 0; s < sbins; s++) {
				float binVal = hs_hist.at<float>(h, s);
				int intensity = cvRound(binVal * 255 / maxval);
				rectangle(hist2d_image, Point(h * scale, s * scale),
					Point((h + 1) * scale - 1, (s + 1) * scale - 1),
					Scalar::all(intensity),
					-1);
			}
			// 输出图像色彩转换
			applyColorMap(hist2d_image, hist2d_image, COLORMAP_JET);
			imshow("H-S Histogram", hist2d_image);
			// imwrite("D:/ hist__2d.png", hist2d_image);
		}
	}
	// 直方图均衡化
	void histogram_eq_demo(Mat& image)
	{
		Mat gray;
		cvtColor(image, gray, COLOR_BGR2GRAY);
		imshow("灰度图像", gray);
		Mat dst;
		equalizeHist(gray, dst);
		imshow("图像直方图均衡化演示", dst);
	}
	// 图像卷积操作
	void blur_demo(Mat& image)
	{
		Mat dst;
		blur(image, dst, Size(23,23), Point(-1, -1));
		// 支持一维卷积---->Size(15,1)
		imshow("图像模糊", dst);
	}
	// 高斯模糊
	void gaussian_blur_demo(Mat& image)
	{
		Mat dst;
		GaussianBlur(image, dst, Size(0, 0), 15);
		// Size(0, 0)是最厉害的模糊
		imshow("高斯模糊图像", dst);
	}
	// 高斯双边模糊
	void bifilter_demo(Mat& image)
	{
		// 磨皮美颜
		Mat dst;
		bilateralFilter(image, dst, 0, 100, 10);
		imshow("双边模糊", dst);
	}
};
int main(int argc, char** argv)
{
	Mat src = imread("迪丽热巴.png",IMREAD_UNCHANGED);
	// Mat是一种特殊的数据类型格式,是一种二维数组,用来存储图片的数据
	// namedWindow("输出窗口", WINDOW_FREERATIO);
	// 只有imshow无法调整图片显示窗口的大小,通过namedWindow调整窗口的大小
	if (src.empty()) {
		cout << "没有找到你的图片" << endl;
		return -1;
	}

	imshow("输出窗口", src);

	demo d;
	d.bifilter_demo(src); 
	waitKey(0);// 设置图片显示时间
	destroyAllWindows();// 释放所有窗口
	return 0;
}

猜你喜欢

转载自blog.csdn.net/hjl011006/article/details/127120771