OpenCv基础(C++)

发布于:2025-07-02 ⋅ 阅读:(21) ⋅ 点赞:(0)

1.图像读取与显示

#include<opencv2/opencv.hpp>
using namespace cv;

Mat src = imread("C:/Users/16385/Desktop/new/photo/1.jpg");//读取图像
Mat src = imread("C:/Users/16385/Desktop/new/photo/1.jpg",IMREAD_GRAYSCALE);
//将读取的图像转为灰色

imshow("输入图像", src);//展示图像

2.色彩空间转换

Mat gray, hsv;

cvtColor(image, hsv, COLOR_BGR2HSV);//将image的RGB色彩空间转换为hsv色彩空间
cvtColor(image, gray, COLOR_BGR2GRAY);

imwrite("D:/hsv.png", hsv);//保存图片到D盘
imwrite("D:/gray.png", gray);

hsv色彩空间  

inrange 检查输入图像中的每个像素,如果像素值位于指定的范围内,则在输出图像(或掩码)中对应位置的像素被设置为白色(或者说是255),否则被设置为黑色(0)

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

	Mat redback=Mat::zeros(image.size(),image.type());
	
	redback = Scalar(40, 40, 200);
	bitwise_not(mask, mask);
	imshow("mask", mask);
	image.copyTo(redback, mask);
	//copyTO的行为
	//只在mask为白色的区域,将image的像素复制到redback。
	//黑色区域保持不变(即保留红色背景)。
	imshow("roi区域提取", redback);
}

3.创建空白图像

这种初始化通常用于:创建空白图像,初始化临时处理矩阵,准备存储三通道数据(如彩色图像)

	Mat m3 = Mat::zeros(Size(512, 512), CV_8UC3);
	//表示每个元素是 8 位无符号整数(0-255),并且每个像素有 3 个通道 8U C3
	m3 = Scalar(0, 0, 255);//设置图像的色彩值
	std::cout << "width: " << m3.cols << "height: " << m3.rows << "channel: " << m3.channels() << std::endl;
	//std::cout << m3 << std::endl;
	imshow("图像", m3);

 1,2,3可以看作是一个像素点

4.拷贝图像

Mat m4;
m3.copyTo(m4);//深拷贝(再创建一份空间,存储)

Mat m4=m3.clone();//深拷贝


Mat m4=m3;//浅拷贝(使用原来的空间,后续更改m4,m3也会更改)

 5.图像的读写

//for循环读写
	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];
			}

		}
	}
	imshow("像素图像",image);



//指针遍历,速度快
	for (int row = 0; row < h; row++)
	{
		uchar* current = image.ptr<uchar>(row);//获取当前行指针
		for (int col = 0; col < w; col++)
		{
			if (dims == 1)//灰度图像
			{
				int pv = *current;
				*current++ = 255 - pv;//先索引,指针再++
			}
			if (dims == 3)//彩色图像
			{
				*current++ = 255 - *current;
				*current++ = 255 - *current;
				*current++ = 255 - *current;
			}

		}
	}

6.图像像素的运算操作

	Mat dst = Mat::zeros(image.size(),image.type());
	Mat m = Mat::zeros(image.size(), image.type());
	m = Scalar(5, 5, 5);
    
    //运算后超过255,值会变成255,反之少于0,为0
	add(image, m, dst);
	subtract(image, m, dst);
	multiply(image, m, dst);
	divide(image, m, dst);

	imshow("运算图像", dst);

7.滑块控件动态改变图像亮度

static void on_track(int b, void* userdata)
{
	Mat image = *((Mat*)userdata);//先将void*指针强制转化为Mat*,再解引用得到image对象
	Mat dst = Mat::zeros(image.size(), image.type());
	Mat m = Mat::zeros(image.size(), image.type());
	m = Scalar(b, b, b);
	add(image, m, dst);
	imshow("亮度调整", dst);
}
void QuickDemo::tracking_bar_demo(Mat& image)//引用传递是浅拷贝
{
	namedWindow("亮度调整", WINDOW_AUTOSIZE);//创建窗口

	//src = image;

	int lightness = 50;
	int max_value = 100;
	createTrackbar("Value Bar:", "亮度调整", &lightness, max_value, on_track,(void*)(&image));//强制将&image转换为void*指针
	on_track(50, &image);
}

8.键盘响应操作

void QuickDemo::key_demo(Mat& image)
{
	Mat dst = Mat::zeros(image.size(), image.type());
	while (true)
	{
		int c = waitKey(0);
		if (c == 27) break;
		if (c == 49)//键盘按下了数字1
		{
			std::cout << "press the number 1" << std::endl;
			cvtColor(image, dst, COLOR_BGR2GRAY);
		}
		if (c == 50)//键盘按下了数字2
		{
			std::cout << "press the number 2" << std::endl;
			cvtColor(image, dst, COLOR_BGR2HSV);
		}
		if (c == 51)//键盘按下了数字3
		{
			std::cout << "press the number 3" << std::endl;
			dst = Scalar(50, 50, 50);
			add(image, dst, dst);
		}
		imshow("图像", dst);
	}
}

9.颜色表操作colormap,applyColorMap()

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_HSV,
		COLORMAP_PINK,
		COLORMAP_HOT,
		COLORMAP_PARULA,
		COLORMAP_MAGMA,
		COLORMAP_INFERNO,
		COLORMAP_PLASMA,
		COLORMAP_VIRIDIS,
		COLORMAP_CIVIDIS,
		COLORMAP_TWILIGHT,
		COLORMAP_TWILIGHT_SHIFTED,
		COLORMAP_TURBO,
		COLORMAP_DEEPGREEN
	};
	Mat dst;
	int index = 0;
	while (true)
	{
		int c = waitKey(1000);
		if (c == 27) break;
		applyColorMap(image, dst, colormap[index]);
		index=(++index)%22;

		imshow("hh", dst);
	}
}

10.图像像素运算(bitwise)

void QuickDemo::bitwise_demo(Mat& image)
{
	Mat m1 = Mat::zeros(Size(255, 255), CV_8UC3);
	Mat m2 = Mat::zeros(Size(255, 255), CV_8UC3);
	rectangle(m1, Rect(100, 100, 80, 80), Scalar(0, 255, 255),-1);
	rectangle(m2, Rect(150, 150, 80, 80), Scalar(255, 255, 0),-1);

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

	Mat dst=m1^m2;//等价于bitwise_xor(m1, m2, dst);
	
	//bitwise_or(m1, m2, dst);
	//bitwise_and(m1, m2, dst);
	//bitwise_not(image, dst);

	imshow("hh", dst);

}

11.通道分离、合并、混合

void QuickDemo::channels_demo(Mat& image)
{
	std::vector<Mat> mv;
	split(image, mv);//分离通道

	//imshow("blue", mv[0]);//opencv设置单通道只显示灰度图(黑白)
	//imshow("green", mv[1]);
	//imshow("red", mv[2]);

	Mat dst;
	mv[1] = 0;//只显示两个通道的颜色
	merge(mv, dst);
	imshow("merge", dst);

	int from_to[] = { 0,2,1,1,2,0 };
	/*  src颜色通道0复制到dst颜色通道2
		src颜色通道1复制到dst颜色通道1
		src颜色通道2复制到dst颜色通道0*/
	mixChannels(image, dst, from_to, 3);//通道混合
	imshow("mix", dst);
}

12.图像像素最大值,最小值,平均值,标准差(minMaxLoc,meanStdDev)

void QuickDemo::pixel_statistic_demo(Mat& image)
{
	double minv, maxv;
	Point minLoc, maxLoc;
	std::vector<Mat> mv;
	split(image, mv);
	for (int i = 0; i < 3; i++)
	{
		minMaxLoc(mv[i], &minv, &maxv, &minLoc, &maxLoc);//这里需要使用mv的单通道
		std::cout << "i:" << i << "minv= " << minv << "maxv= " << maxv << std::endl;
	}
	Mat mean, stddev;
	meanStdDev(image, mean, stddev);
	std::cout << "mean: " << mean << std::endl;
	std::cout << "stddev: " << stddev << std::endl;
}

13.图像几何形状绘制

void QuickDemo::drawing_demo(Mat& image)
{
	rectangle(image, Rect(100, 100, 250, 300), Scalar(0, 0, 255),1, LINE_AA,0);
	circle(image, Point(100, 100), 50, Scalar(255, 0, 0),-1);
	line(image, Point(100, 100), Point(200, 200), Scalar(0, 255, 0),5,8,0);
	ellipse(image, RotatedRect(Point(200, 200), Size(50, 100), 90),Scalar(0,0,255),1, LINE_AA);

	Mat dst;
	dst = Mat::zeros(image.size(), image.type());
	dst = Scalar(0, 255, 0);
	addWeighted(image, 0.7, dst, 0.3,50,dst);
	//addWeighted() 函数用于实现两个图像的加权融合(线性混合)
	imshow("draw", dst);
}

14.随机数

// 方法1:使用默认种子(系统时间)
cv::RNG rng;  // 等价于 cv::RNG rng(time(NULL));

// 方法2:指定种子(生成可重复的随机序列)
cv::RNG rng(12345);  // 固定种子,每次运行生成相同的随机数
//指定种子后,假如第一次随机的是生成的随机数序列:85 22 91 14 67 
                           //重置种子后再次生成:85 22 91 14 67 
void QuickDemo::random_drawing()
{
	Mat canvas = Mat::zeros(Size(512, 512), CV_8UC3);
	RNG rng(12345);//创建对象,12345是固定种子
	while (true)
	{
		int c = waitKey(100);
		if (c == 27) break;
		int x1 = rng.uniform(0, canvas.cols);
		int y1 = rng.uniform(0, canvas.rows);
		int x2 = rng.uniform(0, canvas.cols);
		int y2 = rng.uniform(0, canvas.rows);
        //canvas = Scalar(0, 0, 0);可以每次使窗口变为黑色,每次窗口只显示一条线
		line(canvas, Point(x1, y1), Point(x2, y2), Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255)));
		imshow("hh", canvas);
	}
}

15.多边形填充与绘制

polylines();//绘制折线或轮廓
fillPoly();//填充多边形
drawContours();//绘制 / 填充轮廓
void QuickDemo::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);
	std::vector<Point>pts;
	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(255, 0, 0), 3, LINE_AA, 0);
	fillPoly(canvas, pts, Scalar(0, 255, 0));

	std::vector<std::vector<Point>> contours;
	contours.push_back(pts);
	drawContours(canvas, contours, -1, Scalar(0, 255, 0),-1);
	imshow("hh", canvas);
}

16.鼠标操作与响应setMouseCallback

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);
	if (event == EVENT_LBUTTONDOWN)
	{
		sp.x = x;
		sp.y = y;
		std::cout << sp << std::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);
			imshow("ROI", image(box));//从image提取出box区域
			rectangle(image, box, Scalar(0, 255, 0));
			imshow("鼠标绘制", image);
			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)
			{
				Rect box(sp.x, sp.y, dx, dy);
				temp.copyTo(image);//覆盖原来的图像
				rectangle(image, box, Scalar(0, 255, 0));
				imshow("鼠标绘制", image);
			}

		}
	}
}

void QuickDemo::mouse_drawing_demo(Mat& image)
{
	namedWindow("鼠标绘制", WINDOW_AUTOSIZE);
	setMouseCallback("鼠标绘制", on_draw, (void*)(&image));
	imshow("鼠标绘制", image);
	temp = image.clone();
}

17.图像像素类型转换与归一化(normalize)

void QuickDemo::normal_demo(Mat& image)
{
	Mat dst;
	image.convertTo(image, CV_32F);//将图像转化为32位的浮点数
//这一步是必要的,因为归一化到 [0,1] 范围需要浮点数支持
	normalize(image, dst, 1, 0, NORM_MINMAX);
	imshow("hh", dst);
//OpenCV 的imshow函数在显示浮点数图像时,默认将 [0,1] 范围映射到 [0,255] 显示
}

18.图像缩放与插值(resize)

resize

void QuickDemo::resize_demo(Mat& image)
{
	Mat dst1,dst2;
	int w = image.rows;
	int h = image.cols;
	resize(image, dst1, Size(w / 2, h / 2), 0, 0,INTER_LINEAR);
	imshow("hh", dst1);
	resize(image, dst2, Size(w * 1.2, h * 1.2), 0, 0, INTER_LINEAR);
	imshow("hh1", dst2);
}

19.图像翻转flip

void QuickDemo::filp_demo(Mat& image)
{
	Mat dst1,dst2,dst3;
	flip(image, dst1, 0);//0:沿 X 轴(水平)翻转。
	flip(image, dst2, 1);//	正数(如 1):沿 Y 轴(垂直)翻转。
	flip(image, dst3, -1);//负数(如 - 1):同时沿 X 轴和 Y 轴翻转。
	imshow("hh1", dst1);
	imshow("hh2", dst2);
	imshow("hh3", dst3);
}

20.图像旋转

Mat getRotationMatrix2D(Point2f center, double angle, double scale);
  • center:旋转中心点(图像坐标系中的坐标,例如Point2f(x, y))。
  • angle:旋转角度(单位:度),正值表示逆时针旋转,负值表示顺时针旋转。
  • scale:缩放因子(例如1.0表示保持原大小,0.5表示缩小一半)。
void warpAffine(InputArray src, OutputArray dst, InputArray M, 
                Size dsize, int flags=INTER_LINEAR, 
                int borderMode=BORDER_CONSTANT, 
                const Scalar& borderValue=Scalar());
  • src:输入图像。
  • dst:输出图像,大小由 dsize 指定,类型与输入图像相同。
  • M:2×3 的变换矩阵(通常由 getRotationMatrix2D 或自定义方法生成)。
[ cosθ  -sinθ  0 ]//M旋转时的矩阵
[ sinθ   cosθ  0 ]
  • dsize:输出图像的大小(Size(width, height))。
  • flags:插值方法,常用选项:
    • INTER_LINEAR:双线性插值(默认)。
    • INTER_NEAREST:最近邻插值。
    • INTER_CUBIC:双三次插值(质量更高,但速度较慢)。
  • borderMode:边界填充模式,常用 BORDER_CONSTANT(用常量填充)。
  • borderValue:当 borderMode 为 BORDER_CONSTANT 时的填充值(默认黑色)。

旋转后的宽和高 的计算

void QuickDemo::rotato_demo(Mat& image)
{
	Mat M, dst;
	int w = image.cols;
	int h = image.rows;
	M = getRotationMatrix2D(Point2f(w / 2, h / 2), 45, 1);
	double cos =abs(M.at<double>(0, 0));
	double sin = abs(M.at<double>(0, 1));
	int nw = cos * w + sin * h;//新图像的尺寸
	int nh = sin * w + cos * h;
	M.at<double>(0, 2) += (nw / 2 - w / 2);//x轴偏移量
	M.at<double>(1, 2) += (nh / 2 - h / 2);
	warpAffine(image, dst, M, Size(nw, nh));
	imshow("hh", dst);
}

 21.视频文件摄像头的使用(VideoCapture)

void QuickDemo::vedio_demo()
{
	VideoCapture v(0);//读取的使本地摄像头
	Mat frame;
	while (true)
	{
		v.read(frame);
		if (frame.empty()) break;

		imshow("hh", frame);

		if (waitKey(1) == 27) break;
	}
    v.release();
}



void QuickDemo::vedio_demo()
{
	VideoCapture v("C:/Users/16385/Desktop/new/photo/2.mp4");
	int frame_width = v.get(CAP_PROP_FRAME_WIDTH);//获得v的相关信息
	int frame_height = v.get(CAP_PROP_FRAME_HEIGHT);
	int count = v.get(CAP_PROP_FRAME_COUNT);
	double fps = v.get(CAP_PROP_FPS);
	std::cout << "frame width:" << frame_width << std::endl;
	std::cout << "frame height:" << frame_height << std::endl;
	std::cout << "FPS:" << fps << std::endl;
	std::cout << "Number of Frames:" << count << std::endl;
	VideoWriter writer("D:/test.mp4", v.get(CAP_PROP_FOURCC), fps, Size(frame_width, frame_height), true);//保存视频
	Mat frame;

	while (true)
	{
		v.read(frame);
		if (frame.empty()) break;

		imshow("hh", frame);
		writer.write(frame);
		if (waitKey(1) == 27) break;
	}
	v.release();
	writer.release();
}

22.图像直方图calcHist

calcHist


网站公告

今日签到

点亮在社区的每一天
去签到