OpenCV:图像差分法基础实例(获取差分值及其位置

代码

// win10
// vs2013
// opencv3

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

using namespace std;
using namespace cv;

// 图像差分法

int main()
{
	Mat image = imread("image.jpg");
	Mat test = imread("test.jpg");
	Mat dframe;

	namedWindow("image");
	namedWindow("test");
	namedWindow("dframe");

	// 帧间差分
	// 计算两幅图像各个通道的相对应元素的差的绝对值
	absdiff(test, image, dframe); 
	threshold(dframe, dframe, 70, 255, CV_THRESH_TOZERO);
	imshow("image", image);
	imshow("test", test);
	imshow("dframe", dframe);
	
	int n = 1;
	char diff[20];
	sprintf(diff, "diff//%d.jpg",n);
	//将差分图像存入文件夹
	imwrite(diff, dframe);

	waitKey();

	return 0;
}

效果图

在这里插入图片描述

获取差分值及其矩形框位置

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

using namespace std;
using namespace cv;

//图像差分法

int main()
{
	Mat image = imread("image.jpg");
	Mat test = imread("test.jpg");
	Mat diff;

	namedWindow("image");
	namedWindow("test");
	namedWindow("diff");

	//帧间差分
	//计算两幅图像各个通道的相对应元素的差的绝对值
	absdiff(test, image, diff); 
	threshold(diff, diff, 70, 255, CV_THRESH_TOZERO);
	imshow("image", image);
	imshow("test", test);
	imshow("diff", diff);

	//灰度化与二值化
	Mat diffGray, diffBi;
	cvtColor(diff, diffGray, CV_BGR2GRAY);
	namedWindow("[2]灰度化");
	imshow("[2]灰度化", diffGray);

	threshold(diffGray, diffBi, 50, 255, CV_THRESH_BINARY);
	namedWindow("[3]二值化");
	imshow("[3]二值化", diffBi);

	//膨胀
	Mat diffSwell;
	int g_nStructElementSize = 3; //结构元素(内核矩阵)的尺寸
	Mat element = getStructuringElement(MORPH_RECT, Size(2 * g_nStructElementSize + 1, 2 * g_nStructElementSize + 1), Point(g_nStructElementSize, g_nStructElementSize));
	dilate(diffBi, diffSwell, element);

	namedWindow("[5]膨胀");
	imshow("[5]膨胀", diffSwell);

	//外接矩形
	vector<vector<Point>> contours;
	vector<Vec4i> hierarcy;

	findContours(diffSwell, contours, hierarcy, CV_RETR_EXTERNAL, CHAIN_APPROX_NONE); //查找轮廓

	Mat dst;
	dst = Mat::zeros(diffSwell.size(), CV_8UC3);
	vector<Rect> boundRect(contours.size()); //定义外接矩形集合

	int x0 = 0, y0 = 0, w0 = 0, h0 = 0, num = 0;
	for (int i = 0; i<contours.size(); i++)
	{
		boundRect[i] = boundingRect((Mat)contours[i]); //查找每个轮廓的外接矩形
		drawContours(dst, contours, i, Scalar(0, 0, 255), 2, 8);  //绘制轮廓
		x0 = boundRect[i].x;
		y0 = boundRect[i].y;
		w0 = boundRect[i].width;
		h0 = boundRect[i].height;
		if (w0 > 0 && h0 > 0)//筛选
		{
			rectangle(dst, Point(x0, y0), Point(x0 + w0, y0 + h0), Scalar(0, 255, 0), 2, 8); //绘制第i个外接矩形
			num++;
			//输出diff位置
			cout << "第" << num << "个差分值:" << endl;
			cout << "起点位置:(" << x0 << "," << y0 << ")" << endl;
			cout << "宽:" << w0 << " , " << "高:" << h0 << endl;
			cout << endl;
			//抠图
			//取出目标所在矩形区域生成新图像
			Rect rect(x0, y0, w0, h0);
			Mat ROI = test(rect);
			char f[20];
			sprintf(f, "ob%d.jpg", num);
			string str(f);
			dilate(ROI, ROI, element);
			imwrite(str, ROI);
		}
	}

	namedWindow("[4]轮廓图");
	imshow("[4]轮廓图", dst);
	
	if (num > 0)
	{
		for (int i = 1; i <= num; i++)
		{
			char f[20];
			sprintf(f, "ob%d.jpg", i);
			string str(f);
			Mat ob = imread(str);
			namedWindow(str);
			imshow(str, ob);
		}
	}

	cout << "共有" << num << "个差分值" << endl;

	waitKey();

	return 0;
}

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

获取轮廓内所有点

参考:https://blog.csdn.net/qq_37390630/article/details/70174438?fps=1&locationNum=10&spm=1018.2118.3001.4187

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

using namespace std;
using namespace cv;

//图像差分法

int main()
{
	Mat image = imread("image.jpg");
	Mat test = imread("test.jpg");
	Mat diff;

	namedWindow("image");
	namedWindow("test");
	namedWindow("diff");

	//帧间差分
	//计算两幅图像各个通道的相对应元素的差的绝对值
	absdiff(test, image, diff);
	threshold(diff, diff, 70, 255, CV_THRESH_TOZERO);
	imshow("image", image);
	imshow("test", test);
	imshow("diff", diff);

	//灰度化与二值化
	Mat diffGray, diffBi;
	cvtColor(diff, diffGray, CV_BGR2GRAY);
	namedWindow("[2]灰度化");
	imshow("[2]灰度化", diffGray);

	threshold(diffGray, diffBi, 50, 255, CV_THRESH_BINARY);
	namedWindow("[3]二值化");
	imshow("[3]二值化", diffBi);

	//膨胀
	Mat diffSwell;
	int g_nStructElementSize = 3; //结构元素(内核矩阵)的尺寸
	Mat element = getStructuringElement(MORPH_RECT, Size(2 * g_nStructElementSize + 1, 2 * g_nStructElementSize + 1), Point(g_nStructElementSize, g_nStructElementSize));
	dilate(diffBi, diffSwell, element);

	namedWindow("[5]膨胀");
	imshow("[5]膨胀", diffSwell);

	//外接矩形
	vector<vector<Point>> contours;
	vector<Vec4i> hierarcy;

	findContours(diffSwell, contours, hierarcy, CV_RETR_EXTERNAL, CHAIN_APPROX_NONE); //查找轮廓
	cout << "轮廓总个数:" << contours.size() << endl;

	vector<vector<Point>> ::const_iterator itContours = contours.begin();
	for (; itContours != contours.end(); ++itContours)
		cout << "轮廓包含的点数:" << itContours->size() << endl;

	Mat dst;
	dst = Mat::zeros(diffSwell.size(), CV_8UC3);
	//vector<Rect> boundRect(contours.size()); //定义外接矩形集合

	//int x0 = 0, y0 = 0, w0 = 0, h0 = 0, num = 0;
	for (int i = 0; i < contours.size(); i++)
	{
		Scalar color = Scalar(255, 255, 255);

		drawContours(dst, contours, i, color, 1, 8, hierarcy, 0, Point());

		printf("\n输出轮廓序号,第%d个轮廓: \n", i);

		cout << "输出轮廓包含点的总数:  " << contours[i].size() << endl;    //试试看输出该轮廓点的总数

		// 下面三行来自http://www.opencv.org.cn/forum.php?mod=viewthread&tid=38297&page=4
		// contours[i][0]表示第i个轮廓第0个点
		cout << "输出轮廓第0个点的坐标  " << contours[i][0] << endl;     //试试看输出轮廓第一个点的坐标 x,y
		cout<< "输出轮廓第0个点的x坐标  " << contours[i][0].x << endl;  //试试看输出轮廓第一个点的横坐标 x
		cout<< "输出轮廓第0个点的y坐标  " << contours[i][0].y << endl;  //试试看输出轮廓第一个点的纵坐标 y
	}

	namedWindow("[4]轮廓图");
	imshow("[4]轮廓图", dst);

	waitKey();

	return 0;
}

在这里插入图片描述

  • 7
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
您好!要使用OpenCV进行三帧差分法,您可以按照以下步骤进行操作: 1. 导入必要的库: ```python import cv2 import numpy as np ``` 2. 读取视频文件,并初始化变量: ```python cap = cv2.VideoCapture('your_video_file.mp4') ret, frame1 = cap.read() ret, frame2 = cap.read() ret, frame3 = cap.read() ``` 3. 循环遍历视频的每一帧: ```python while cap.isOpened(): # 计算帧差 diff1 = cv2.absdiff(frame1, frame2) diff2 = cv2.absdiff(frame2, frame3) # 将帧差图像转换为灰度图 gray1 = cv2.cvtColor(diff1, cv2.COLOR_BGR2GRAY) gray2 = cv2.cvtColor(diff2, cv2.COLOR_BGR2GRAY) # 对灰度图进行二化处理 _, thresh1 = cv2.threshold(gray1, 30, 255, cv2.THRESH_BINARY) _, thresh2 = cv2.threshold(gray2, 30, 255, cv2.THRESH_BINARY) # 对二化后的图像进行膨胀操作,以去除噪声 kernel = np.ones((5, 5), np.uint8) dilated1 = cv2.dilate(thresh1, kernel, iterations=3) dilated2 = cv2.dilate(thresh2, kernel, iterations=3) # 计算两个帧差的逻辑与,得到前景物体 final_frame = cv2.bitwise_and(dilated1, dilated2) # 显示前景物体 cv2.imshow('Motion Detection', final_frame) # 更新帧 frame1 = frame2 frame2 = frame3 # 读取下一帧 ret, frame3 = cap.read() # 按下 'q' 键退出循环 if cv2.waitKey(1) & 0xFF == ord('q'): break # 释放资源 cap.release() cv2.destroyAllWindows() ``` 这个代码片段会打开视频文件,并对每三帧进行差分计算,最终显示前景物体。 请注意,您需要将代码中的 `'your_video_file.mp4'` 替换为您自己的视频文件路径。此外,您还可以根据需要调整阈、膨胀操作和其他参数来优化结果。 希望对您有所帮助!如果您还有其他问题,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值