OpenCV图像处理——对比两张图像差异的位置并标记

前言

1.有一个小游戏,就给出两张内容几乎差不多全部相同的图像,让大家在最快的时间内找出两个图像中有几处不同地方,我这里试着用OpenCV实现这个功能。
2.我的编程环境是Windows 10 64位,IDE是VS2019,配置了OpenCV 4.5,实现语言是C++。是于如果配置以上的环境,可以看我之前写的博文。

一、资源准备

可以在网上搜《图片大找茬》,然后下载两张相似的图像,但图像的大小必须一样。下面是我指用的两张图像。如果不一样,就用resize()这个函数去调整两张图像的尺寸。

在这里插入图片描述
在这里插入图片描述

二、代码演示

1.这里用到的是OpenCV图像基本运算,两图相减。使用的API是subtract()。
代码是传入两张图像

void imageSubtract(Mat &image1, Mat &image2)
{
	if ((image1.rows != image2.rows) || (image1.cols != image2.cols))
	{
		if (image1.rows > image2.rows)
		{
			resize(image1, image1, image2.size(), 0, 0, INTER_LINEAR);
		}
		else if (image1.rows < image2.rows)
		{
			resize(image2, image2, image1.size(), 0, 0, INTER_LINEAR);
		}
	}

	Mat image1_gary, image2_gary;
	if (image1.channels() != 1)
	{
		cvtColor(image1, image1_gary, COLOR_BGR2GRAY);
	}
	if (image2.channels() != 1)
	{
		cvtColor(image2, image2_gary, COLOR_BGR2GRAY);
	}

	Mat frameDifference, absFrameDifferece;
	Mat previousGrayFrame = image2_gary.clone();
	//图1减图2
	subtract(image1_gary, image2_gary, frameDifference, Mat(), CV_16SC1);

	//取绝对值
	absFrameDifferece = abs(frameDifference);

	//位深的改变
	absFrameDifferece.convertTo(absFrameDifferece, CV_8UC1, 1, 0);
	imshow("absFrameDifferece", absFrameDifferece);
	Mat segmentation;
	
	//阈值处理(这一步很关键,要调好二值化的值)
	threshold(absFrameDifferece, segmentation,100, 255, THRESH_BINARY);

	//中值滤波
	medianBlur(segmentation, segmentation, 3);

	//形态学处理(开闭运算)
	//形态学处理用到的算子
	Mat morphologyKernel = getStructuringElement(MORPH_RECT, Size(3, 3), Point(-1, -1));
	morphologyEx(segmentation, segmentation, MORPH_CLOSE, morphologyKernel, Point(-1, -1), 2, BORDER_REPLICATE);

	//显示二值化图片
	imshow("segmentation", segmentation);

	//找边界
	vector< vector<Point> > contours;
	vector<Vec4i> hierarchy;
	findContours(segmentation, contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));//CV_RETR_TREE
	vector< vector<Point> > contours_poly(contours.size());

	vector<Rect> boundRect;
	boundRect.clear();

	for (int index = 0; index < contours.size(); index++)
	{
		approxPolyDP(Mat(contours[index]), contours_poly[index], 3, true);
		Rect rect = boundingRect(Mat(contours_poly[index]));
		rectangle(image2, rect, Scalar(0, 255, 0), 2);
	}
	imshow("效果图", image2);
}

2.运行效果
在这里插入图片描述

结语

例子很简单,但是这个方法用到移动目标追踪的上去,就是两帧差,学习交流可加企鹅群:767133823

### 使用Python OpenCV实现图像对比 为了使用Python和OpenCV进行图像比较,可以采用结构相似性指数(SSIM)、均方误差(MSE)等方法来量化两幅图片之间的差异。下面展示了一个简单的例子,通过计算两张输入图像间的SSIM值来进行图像对比。 #### 计算均方误差(Mean Squared Error) 均方误差是一种衡量两个图像之间差别的简单方式: ```python import numpy as np def mse(imageA, imageB): err = np.sum((imageA.astype("float") - imageB.astype("float")) ** 2) err /= float(imageA.shape[0] * imageA.shape[1]) return err ``` 此函数接收两个参数`imageA` 和 `imageB` ,它们代表要比较的原始灰度图或彩色图像[^1]。 #### 结构相似性指数测量 (Structural Similarity Index Measure) 除了MSE之外,还可以考虑更复杂的指标——结构相似性指数(SSIM),该指标不仅关注像素级别的变化还考虑到人类视觉系统的特性: ```python from skimage.metrics import structural_similarity as ssim import cv2 def compare_images(imageA, imageB): grayA = cv2.cvtColor(imageA, cv2.COLOR_BGR2GRAY) grayB = cv2.cvtColor(imageB, cv2.COLOR_BGR2GRAY) score, diff = ssim(grayA, grayB, full=True) diff = (diff * 255).astype("uint8") thresh = cv2.threshold(diff, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)[1] cnts = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[-2] for c in cnts: (x, y, w, h) = cv2.boundingRect(c) cv2.rectangle(imageA, (x, y), (x + w, y + h), (0, 0, 255), 2) cv2.rectangle(imageB, (x, y), (x + w, y + h), (0, 0, 255), 2) return score, imageA, imageB, diff ``` 上述代码片段定义了`compare_images()` 函数用于加载转换待比较的图像到灰度模式;接着调用skimage中的ssim() 方法获取两者间SSIM得分以及差异映射矩阵;最后基于阈值处理后的二值化结果找到轮廓,在原图中标记出来不同的区域
评论 31
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

知来者逆

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值