OpenCV4学习代码

OpenCV4学习代码

OpenCV学堂b站课程路径链接

1. 打开并展示图像

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


using namespace std;
using namespace cv;


int main(int argc, char** argv)
{
	// 灰度
	Mat src = imread("D:\\images\\city-walk.png", IMREAD_GRAYSCALE);

	if (src.empty()) {
		cout << "image not exits" << endl;
		return 0;
	}

	//  自适应窗口
	namedWindow("输入窗口", WINDOW_FREERATIO);
	imshow("输入窗口", src);
	// 等待2秒
	waitKey(2000);

	cout << src.depth() << endl;
	destroyAllWindows();
	return 0;

}


2. 颜色空间转换

#include "quick_opencv.h"


void QuickDemo::colorSpace_Demo(Mat &image) {
	Mat gray, hsv;
	cvtColor(image, hsv, COLOR_BGR2HSV);
	cvtColor(image, gray, COLOR_BGR2GRAY);
	imshow("HSV", hsv);
	imshow("灰度", gray);
	//imwrite("D:/hsv.png", hsv);
}

3. 图片克隆与通道数

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

using namespace std;
using namespace cv;


int main(int argc, char** argv)
{

	Mat image = imread("D:\\images\\lena.png");
	Mat m1, m2;
	m1 = image.clone();
	image.copyTo(m2);
	// CV_8UC1 单通道图片
	Mat m3 = Mat::zeros(Size(4, 4), CV_8UC1);
	cout << m3 << endl;
	//[0, 0, 0, 0;
	//0, 0, 0, 0;
	//0, 0, 0, 0;
	//0, 0, 0, 0]
	// 3通道,存储方式问bgrbgr....
	Mat m4 = Mat::zeros(Size(4, 4), CV_8UC3);
	cout << m4 << endl;
	//[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
	//0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
	//0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
	//0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

	m4 = 127;
	cout << m4 << endl;
	//[127, 0, 0, 127, 0, 0, 127, 0, 0, 127, 0, 0;
	//127, 0, 0, 127, 0, 0, 127, 0, 0, 127, 0, 0;
	//127, 0, 0, 127, 0, 0, 127, 0, 0, 127, 0, 0;
	//127, 0, 0, 127, 0, 0, 127, 0, 0, 127, 0, 0]
	// 同时对三个通道赋值必须用Scalar,否则只会处理一个通道
	m4 = Scalar(127,127, 127);
	cout << m4 << endl;

	waitKey(0);
	destroyAllWindows();
	return 0;

}

4. 图像像素的读写操作

void QuickDemo::pixel_visit_demo(Mat &image) {
	int w = image.cols;
	int h = image.rows;
	int dims = image.channels();

	// 下标方式
	//for (int row = 0; row < h; row++) {
	//	for (int col = 0; col < w; 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 < h; row++) {
		uchar* current_row = image.ptr<uchar>(row);
		for (int col = 0; col < w; col++) {
			if (dims == 1) {
				*current_row++ = 255 - *current_row;
			}
			if (dims == 3) {
				*current_row++ = 255 - *current_row;
				*current_row++ = 255 - *current_row;
				*current_row++ = 255 - *current_row;
			}
		}

	}
	imshow("像素读写演示", image);
}

5. 调api实现加减乘除

void QuickDemo::operators_demo(Mat& image) {
	Mat dst;
	// 加法
	/*dst = image + Scalar(50, 50, 50);
	imshow("加法操作", dst);*/

	Mat m = Mat::zeros(image.size(), image.type());
	m = Scalar(2, 2, 2);
	multiply(image, m, dst);
	//imshow("乘法法操作", dst);


	
	Mat dst_2 = Mat::zeros(image.size(), image.type());
	Mat m_2 = Mat::zeros(image.size(), image.type());
	m_2 = Scalar(50, 50, 50);

	// 模拟加法
	//int h = image.rows;
	//int w = image.cols;
	//for (int row = 0; row < h; row++) {
	//	for (int col = 0; col < w; col++) {
	//		Vec3b i_v = image.at<Vec3b>(row, col);
	//		Vec3b m_v = m_2.at<Vec3b>(row, col);
	//		dst_2.at<Vec3b>(row, col)[0] = saturate_cast<uchar>(i_v[0] + m_v[0]);
	//		dst_2.at<Vec3b>(row, col)[1] = saturate_cast<uchar>(i_v[1] + m_v[1]);
	//		dst_2.at<Vec3b>(row, col)[2] = saturate_cast<uchar>(i_v[2] + m_v[2]);
	//	}
	//}
	//imshow("加法操作模拟", dst_2);.

	add(image, m_2, dst_2);
	imshow("加法", dst_2);

	subtract(image, m_2, dst_2);
	imshow("减法", dst_2);

	divide(image, m_2, dst_2);
	imshow("除法", dst_2);

}

6. 使用track bar实时调整图像的亮度



Mat dst, m, src;
int lightness = 50;

static void on_track(int, void*) {
	m = Scalar(lightness, lightness, lightness);
	add(src, m, dst);
	imshow("亮度调整", dst);
}


void QuickDemo::tracking_bar_demo(Mat& image) {
	namedWindow("亮度调整", WINDOW_AUTOSIZE);

	dst = Mat::zeros(image.size(), image.type());
	m = Mat::zeros(image.size(), image.type());
	src = image;
	int max_value = 100;
	createTrackbar("Value Bar:", "亮度调整", &lightness, max_value, on_track);
	on_track(50, 0);

}

在这里插入图片描述

7. 实时亮度调整,使用类的形式

static void on_track(int b, void* user_data) {
	// 第一个参数必须是int,第二个是void*
	Mat image = *((Mat*)user_data);
	Mat dst = Mat::zeros(image.size(), image.type());
	Mat m = Mat::zeros(image.size(), image.type());
	m = Scalar(b, b, b);
	subtract(image, m, dst);
	imshow("亮度调整", dst);
}


void QuickDemo::tracking_bar_demo(Mat& image) {
	namedWindow("亮度调整", WINDOW_AUTOSIZE);
	int lightness = 50;
	int max_value = 100;
	createTrackbar("value bar:", "亮度调整", &lightness, max_value, on_track, (void*)(&image));
	on_track(50, &image);
}

同时调整亮度和对比度

static void on_lightness(int a, void* user_data) {
	Mat image = *((Mat*)user_data);
	Mat dst = Mat::zeros(image.size(), image.type());
	Mat m = Mat::zeros(image.size(), image.type());
	addWeighted(image, 1.0, m, 0, a, dst);
	imshow("亮度对比度调整", dst);
}

static void on_contrast(int b, void* user_data) {
	Mat image = *((Mat*)user_data);
	Mat dst = Mat::zeros(image.size(), image.type());
	Mat m = Mat::zeros(image.size(), image.type());
	addWeighted(image, b/200.0, m, 0, 0, dst);
	imshow("亮度对比度调整", dst);

}

void QuickDemo::tracking_bar_demo(Mat& image) {
	namedWindow("亮度对比度调整", WINDOW_AUTOSIZE);
	int lightness = 50;
	int max_lightness_value = 100;

	int contrastness = 100;
	createTrackbar("lightnetss value bar:", "亮度对比度调整", &lightness, max_lightness_value, on_lightness, (void*)(&image));
	createTrackbar("contrast value bar:", "亮度对比度调整", &contrastness, 200, on_lightness, (void*)(&image));
	on_lightness(50, &image);
}

8. 键盘响应

void QuickDemo::key_demo(Mat &image) {
	Mat dst = Mat::zeros(image.size(), image.type());
	while (true)
	{
		int c = waitKey(1000);
		cout << c << endl;
		// 按Esc退出循环
		if (c == 27) {
			break;
		}
		// 按数字1转灰度图
		if (c == 49) {
			cout << "you enter #1" << endl;
			cvtColor(image, dst, COLOR_BGR2GRAY);
		}
		// 按数字2转换成hsv
		if (c == 50) {
			cout << "you enter #2" << endl;
			cvtColor(image, dst, COLOR_BGR2HSV);
		}
		// 按数字3亮度加50
		if (c == 51) {
			cout << "you enter #3" << endl;
			dst = Scalar(50, 50, 50);
			add(image, dst, dst);
		}
		imshow("键盘响应", dst);
	}
}

9. 颜色风格

void QuickDemo::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(2000);
		if (c == 27) {
			break;
		}
		applyColorMap(image, dst, colormap[index % 19]);
		index++;
		imshow("颜色风格", dst);
	}
}

10. 图像的与或非 异或

void QuickDemo::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);
	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("bitwise_and", dst);

	bitwise_or(m1, m2, dst);
	imshow("bitwise_or", dst);

	bitwise_not(image, dst);
	//Mat dst = ~image;
	imshow("bitwise_not", dst);

	bitwise_xor(m1, m2, dst);
	imshow("bitwise_xor", dst);
}

11. 通道分离 合并和交换

void QuickDemo::channels_demo(Mat &image) {
	vector<Mat> mv;
	// 分离通道
	split(image, mv);
	imshow("B", mv[0]);
	imshow("G", mv[1]);
	imshow("R", mv[2]);

	Mat dst;
	mv[1] = 0;
	//mv[2] = 0;
	// 合并通道
	merge(mv, dst);
	imshow("蓝色", dst);
	
	// 0通道到2 1通道到1 2通道到0
	int from_to[] = { 0, 2, 1, 1, 2, 0 };

	mixChannels(image, dst, from_to, 3);
	imshow("通道交换1", dst);
	mixChannels(&image, 1, &dst, 1, from_to, 3);
	imshow("通道交换2", dst);
}

12. 色彩空间转换来抠图

void QuickDemo::inrange_demo(Mat &image) {
	Mat hsv;
	cvtColor(image, hsv, COLOR_BGR2HSV);
	imshow("hsv", hsv);
	Mat mask;
	inRange(hsv, Scalar(35, 43, 46), Scalar(77, 255, 255), mask);
	imshow("mask", mask);

	Mat redback(image.size(), image.type());
	redback = Scalar(10, 10, 200);
	bitwise_not(mask, mask);

	copyTo(image, redback, mask);
	imshow("roi change", redback);

}

13. 像素值统计

void QuickDemo::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.channel:" << i << " min value:" << minv << " max value: " << maxv << endl;
	}

	Mat mean, stddev;
	meanStdDev(image, mean, stddev);
	cout << "mean: " << mean << endl;
	cout << "stddev: " << stddev << endl;
}

14. 基础图形绘制

void QuickDemo::drawing_demo(Mat &image) {
	Rect rect;
	rect.x = 550;
	rect.y = 80;
	rect.width = 230;
	rect.height = 230;

	Mat bg = Mat::zeros(image.size(), image.type());
	rectangle(bg, rect, Scalar(0, 0, 255), -1, 8, 0);
	circle(bg, Point(550, 80), 20, Scalar(255, 0, 0), -1, 8, 0);

	Mat dst(image.size(), image.type());
	addWeighted(image, 0.7, bg, 0.5, 0, dst);

	line(dst, Point(550, 80), Point(780, 310), Scalar(255, 0, 0), 2, 8, 0);
	
	RotatedRect rrt;
	// 椭圆对的质心
	rrt.center = Point(550, 80);
	// 椭圆的长宽
	rrt.size = Size(100, 200);
	// 旋转角度
	rrt.angle = 90.0;
	ellipse(dst, rrt, Scalar(0, 255, 0), 2, 8);
	imshow("矩形", dst);

}

15. 产生随机数

void QuickDemo::random_drawing() {

	Mat canvas = Mat::zeros(Size(512, 512), CV_8UC3);
	RNG rng(124);

	while (true) {
		int c = waitKey(10);
		if (c == 27) {
			break;
		}
		
		int x1 = rng.uniform(0, 512);
		int y1 = rng.uniform(0, 512);
		int x2 = rng.uniform(0, 512);
		int y2 = rng.uniform(0, 512);

		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), 2, LINE_AA, 0);
		imshow("canvas", canvas);
	}

}

16. 绘制多边形

void QuickDemo::ployline_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;
	pts.push_back(p1);
	pts.push_back(p2);
	pts.push_back(p3);
	pts.push_back(p4);
	pts.push_back(p5);
	// 方法一: 画多边形,并填充,注意,这里不能直接把thickness设置成-1,而是需要调用fillPoly
	//polylines(canvas, pts, true, Scalar(0, 0, 255), 2, 8, 0);
	//fillPoly(canvas, pts, Scalar(0, 255, 0), LINE_AA, 0);
	// 方法二: 使用drawContours
	vector<vector<Point>> contours;
	contours.push_back(pts);
	// -1是draw这个vector里面的说有polyline, 第二个-1是填充
	drawContours(canvas, contours, -1, Scalar(255, 0, 255), -1, LINE_AA);
	imshow("ploylines", canvas);

}

17. 鼠标操作与响应


Point sp(-1, -1);
Point ep(-1, -1);
Mat temp;
static void on_draw(int event, int x, int y, int flags, void* userdata) {
	Mat image = *((Mat*)userdata);
	Mat back = image.clone();
	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);
			rectangle(image, box, Scalar(255, 255, 0), 2, LINE_AA, 0);
			imshow("绘制多边形", image);
			imshow("ROI", image(box));
		}
		sp.x = -1;
		sp.y = -1;
	}
	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) {
				temp.copyTo(image);
				Rect box(sp.x, sp.y, dx, dy);
				rectangle(image, box, Scalar(255, 255, 0), 2, LINE_AA, 0);
				imshow("绘制多边形", image);
			}
		}
	}
}

void QuickDemo::mouse_drawing_demo(Mat &image) {

	namedWindow("绘制多边形", WINDOW_AUTOSIZE);
	setMouseCallback("绘制多边形", on_draw, (void *) &image);
	imshow("绘制多边形", image);
	temp = image.clone();
}

18.图像归一化

void QuickDemo::norm_demo(Mat &image) {
	Mat dst;
	image.convertTo(image, CV_32F);
	normalize(image, dst, 1.0, 0, NORM_MINMAX);
	imshow("图像归一化", dst);

}

19. 图像缩放与插值

void QuickDemo::resize_demo(Mat &image) {
	Mat zoomin, zoomout;
	int h = image.rows;
	int w = image.cols;
	resize(image, zoomin, Size(w / 2, h / 2), INTER_LINEAR);
	imshow("zoomin", zoomin);
	resize(image, zoomin, Size(w * 2, h * 2), INTER_LINEAR);
	imshow("zoomin", zoomin);
}

20. 图像翻转

void QuickDemo::flip_demo(Mat &image) {
	Mat dst;
	// 上下翻转
	flip(image, dst, 0); 
	imshow("flip0", dst);

	// 左右翻转
	flip(image, dst, 1);
	imshow("flip1", dst);

	// 旋转180度
	flip(image, dst, -1);
	imshow("flip-1", dst);
}

21. 利用仿射编号进行旋转

void QuickDemo::rotate_demo(Mat &image) {
	Mat dst, M;
	int w = image.cols;
	int h = image.rows;
	M = getRotationMatrix2D(Point2f(w / 2, h / 2), 45, 1.0);
	// 裁剪了
	//warpAffine(image, dst, M, image.size(), INTER_LINEAR, 0, Scalar(255, 0, 255));

	double cos = abs(M.at<double>(0, 0));
	double sin = abs(M.at<double>(0, 1));

	double nw = w * cos + h * sin;
	double nh = h * cos + w * sin;
	
	M.at<double>(0, 2) += nw / 2 - w / 2;
	M.at<double>(1, 2) += nh / 2 - h / 2;
	// 没有裁剪
	warpAffine(image, dst, M, Size(nw, nh), INTER_LINEAR, 0, Scalar(255, 0, 255));
	imshow("warpaffine", dst);
}

22. 视频文件和使用摄像头

void QuickDemo::video_demo() {
	VideoCapture capture(0);
	Mat frame;
	while (true) {
		capture.read(frame);
		if (frame.empty()) {
			break;
		}
		flip(frame, frame, 1);
		imshow("frame", frame);

		int c = waitKey(1);
		if (c == 27) {
			break;
		}
	}
	capture.release();
}

23. 视频信息读取与保存


void QuickDemo::video_demo() {
	VideoCapture capture("D:\\images\\01.mp4");
	

	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);
	double fps = capture.get(CAP_PROP_FPS);
	double fourcc = capture.get(CAP_PROP_FOURCC);

	VideoWriter writer("D:/images/01_gray.mp4", capture.get(CAP_PROP_FOURCC), fps, Size(frame_width, frame_height), true);


	cout << "width: " << frame_width << " height: " << frame_height << endl;
	cout << "frame count: " << count << " fps: " << fps << endl;
	cout << "fourcc: " << fourcc << endl;

	Mat frame;

	while (true) {
		capture.read(frame);
		if (frame.empty()) {
			break;
		}
		cvtColor(frame, frame, COLOR_BGR2GRAY);
		imshow("frame", frame);
		writer.write(frame);
		int c = waitKey(1);
		if (c == 27) {
			break;
		}
	}
	capture.release();
	writer.release();
}

24. 图像的直方图

void QuickDemo::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;

	// 计算直方图
	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 Demo", histImage);

}

在这里插入图片描述

25. 二维直方图

void QuickDemo::histogram_2d_demo(Mat &image) {
	Mat hsv, hs, hs_hist;
	cvtColor(image, hsv, COLOR_BGR2HSV);
	// h通道一共有分成30份, s通道一共分成32份
	int hbins = 30, sbins = 32;
	int hist_bins[] = { hbins, sbins };
	// h通道取值范围是[0, 180]
	float h_range[] = { 0, 180 };
	// s通道取值范围是[0, 256]
	float s_range[] = { 0, 256 };
	const float* hs_ranges[] = { h_range, s_range };
	int hs_channels[] = { 0, 1 };
	// 入参分别为:
	// 原图引用, 一共1张图, 需要处理这张图的0,1通道, 一个空的Mask(没有遮罩),输出结果矩阵,需要处理的通道数是2,
	// hist_bins:每一个通道分成多少份, hs_ranges:每一份的取值范围, 是否均匀分配,是否累加
	calcHist(&hsv, 1, hs_channels, Mat(), hs_hist, 2, hist_bins, hs_ranges, true, false);
	cout << "hs_hist shape: " << hs_hist.size() << endl;
	double maxVal = 0;
	minMaxLoc(hs_hist, 0, &maxVal, 0, 0);
	int scale = 20;
	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);
		}
	}
	Mat dst;
	applyColorMap(hist2d_image, dst, COLORMAP_OCEAN);
	imshow("H-S Histogram", dst);
}

在这里插入图片描述

26. 直方图均衡化

void QuickDemo::histogram_eq_demo(Mat &image) {
	//Mat gray;
	//cvtColor(image, gray, COLOR_BGR2GRAY);
	//imshow("灰度图像", gray);

	//Mat dst;
	//equalizeHist(gray, dst);
	//imshow("直方图均衡化", dst);

	// 彩色图片均衡化
	// 转换成hsv色域,然后提取v通道进行均衡化
	Mat hsv;
	cvtColor(image, hsv, COLOR_BGR2HSV);

	vector<Mat> mv;
	split(hsv, mv);

	Mat v = mv[2];
	equalizeHist(v, v);
	mv[2] = v;

	Mat new_hsv;
	merge(mv, new_hsv);
	imshow("均衡化hsv", new_hsv);

	Mat dst;
	cvtColor(new_hsv, dst, COLOR_HSV2BGR);
	imshow("均衡化bgr", dst);
}

在这里插入图片描述

27. 卷积操作

void QuickDemo::blur_demo(Mat &image) {
	Mat dst;
	blur(image, dst, Size(50, 50), Point(-1, -1));
	imshow("图像卷积", dst);
}

28. 高斯模糊

高斯模糊的公式,重点在于sigma的设置

请添加图片描述

void QuickDemo::GaussianBlur_demo(Mat &image) {
	Mat dst;
	// size 必须是偶数, size和sigma只有一个是可以生效的.所以一般设置sigma即可
	GaussianBlur(image, dst, Size(0, 0), 5);
	imshow("GaussianBlur", dst);
}

在这里插入图片描述

28. 高斯双边模糊用来美颜

高斯双边模糊的原理

请添加图片描述

void QuickDemo::bilblur_demo(Mat &image) {
	Mat dst;
	bilateralFilter(image, dst, 0, 100, 10);
	imshow("高斯双边模糊", dst);
}

在这里插入图片描述

29. 基于opencv的SSD人脸识别

这里利用了opencv官方的一个demo模型,模型描述可以直接在C:\opencv4\opencv-4.5.5\samples\dnn\face_detector中,模型可以在下面地址下载:
SSD人脸检测模型下载

void QuickDemo::face_detection_demo() {
	VideoCapture capture(0);
	string root_dir = "D:/project/opencv4/opencv_tutorial-master/data/models/face_detector/";
	dnn::Net net = dnn::readNetFromTensorflow(root_dir + "opencv_face_detector_uint8.pb", root_dir+"opencv_face_detector.pbtxt");
	
	Mat frame;
	while (true) {
		int key = waitKey(1);
		if (key == 27) {
			break;
		}
		capture.read(frame);
		flip(frame, frame, 1);
		Mat blob = dnn::blobFromImage(frame, 1.0, Size(300, 300), Scalar(104, 177, 123), false, false);
		net.setInput(blob);
		Mat probs = net.forward();
		cout << "probs mat size: " << probs.size << endl;
		Mat detectionMat(probs.size[2], probs.size[3], CV_32F, probs.ptr<float>());
		cout << "detection mat size: " << detectionMat.size << endl;
		
		for (size_t i = 0; i < detectionMat.rows; ++i) {
			double confidence = detectionMat.at<float>(i, 2);
			if (confidence > 0.5) {
				int x1 = static_cast<int>(detectionMat.at<float>(i, 3)*frame.cols);
				int y1 = static_cast<int>(detectionMat.at<float>(i, 4)*frame.rows);
				int x2 = static_cast<int>(detectionMat.at<float>(i, 5)*frame.cols);
				int y2 = static_cast<int>(detectionMat.at<float>(i, 6)*frame.rows);
				rectangle(frame, Rect(x1, y1, x2-x1, y2-y1), Scalar(255, 0, 255), 2, 8, 0);
				putText(frame, to_string(confidence), Point(x1, y1), FONT_HERSHEY_COMPLEX, 1, Scalar(0, 255, 0), 2);
			}
		}
		imshow("capture", frame);
	}
	capture.release();
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


学习编程是顺着互联网的发展潮流,是一件好事。新手如何学习编程?其实不难,不过在学习编程之前你得先了解你的目的是什么?这个很重要,因为目的决定你的发展方向、决定你的发展速度。
IT行业是什么工作做什么?IT行业的工作有:产品策划类、页面设计类、前端与移动、开发与测试、营销推广类、数据运营类、运营维护类、游戏相关类等,根据不同的分类下面有细分了不同的岗位。
女生学Java好就业吗?女生适合学Java编程吗?目前有不少女生学习Java开发,但要结合自身的情况,先了解自己适不适合去学习Java,不要盲目的选择不适合自己的Java培训班进行学习。只要肯下功夫钻研,多看、多想、多练
Can’t connect to local MySQL server through socket \'/var/lib/mysql/mysql.sock问题 1.进入mysql路径
oracle基本命令 一、登录操作 1.管理员登录 # 管理员登录 sqlplus / as sysdba 2.普通用户登录
一、背景 因为项目中需要通北京网络,所以需要连vpn,但是服务器有时候会断掉,所以写个shell脚本每五分钟去判断是否连接,于是就有下面的shell脚本。
BETWEEN 操作符选取介于两个值之间的数据范围内的值。这些值可以是数值、文本或者日期。
假如你已经使用过苹果开发者中心上架app,你肯定知道在苹果开发者中心的web界面,无法直接提交ipa文件,而是需要使用第三方工具,将ipa文件上传到构建版本,开...
下面的 SQL 语句指定了两个别名,一个是 name 列的别名,一个是 country 列的别名。**提示:**如果列名称包含空格,要求使用双引号或方括号:
在使用H5混合开发的app打包后,需要将ipa文件上传到appstore进行发布,就需要去苹果开发者中心进行发布。​
+----+--------------+---------------------------+-------+---------+
数组的声明并不是声明一个个单独的变量,比如 number0、number1、...、number99,而是声明一个数组变量,比如 numbers,然后使用 nu...
第一步:到appuploader官网下载辅助工具和iCloud驱动,使用前面创建的AppID登录。
如需删除表中的列,请使用下面的语法(请注意,某些数据库系统不允许这种在数据库表中删除列的方式):
前不久在制作win11pe,制作了一版,1.26GB,太大了,不满意,想再裁剪下,发现这次dism mount正常,commit或discard巨慢,以前都很快...
赛门铁克各个版本概览:https://knowledge.broadcom.com/external/article?legacyId=tech163829
实测Python 3.6.6用pip 21.3.1,再高就报错了,Python 3.10.7用pip 22.3.1是可以的
Broadcom Corporation (博通公司,股票代号AVGO)是全球领先的有线和无线通信半导体公司。其产品实现向家庭、 办公室和移动环境以及在这些环境...
发现个问题,server2016上安装了c4d这些版本,低版本的正常显示窗格,但红色圈出的高版本c4d打开后不显示窗格,
TAT:https://cloud.tencent.com/document/product/1340