查找两张图像差异的地方并标记 python版&c++版
程序员文章站
2022-06-01 15:45:46
...
python版已验证代码参考:
# -*- coding: utf-8 -*-
from skimage.metrics import structural_similarity
import imutils
import cv2
# 加载两张图片并将他们转换为灰度
imageA = cv2.imread(r"1.jpg")
imageB = cv2.imread(r"2.jpg")
grayA = cv2.cvtColor(imageA, cv2.COLOR_BGR2GRAY)
grayB = cv2.cvtColor(imageB, cv2.COLOR_BGR2GRAY)
# 计算两个灰度图像之间的结构相似度指数
(score,diff) = structural_similarity(grayA,grayB,full = True)
diff = (diff *255).astype("uint8")
print("SSIM:{}".format(score))
# 找到不同点的轮廓以致于我们可以在被标识为“不同”的区域周围放置矩形
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)
cnts = cnts[0] if imutils.is_cv2() else cnts[1]
# 找到一系列区域,在区域周围放置矩形
for c in cnts:
(x,y,w,h) = cv2.boundingRect(c)
cv2.rectangle(imageA,(x,y),(x+w,y+h),(0,255,0),2)
cv2.rectangle(imageB,(x,y),(x+w,y+h),(0,255,0),2)
# 用cv2.imshow 展现最终对比之后的图片, cv2.imwrite 保存最终的结果图片
cv2.imshow("Modified", imageB)
cv2.imwrite(r"result.bmp", imageB)
cv2.waitKey(0)
运行结果:
缺点:不适合用于工业的缺陷检测,仅仅适用于相同尺寸的图片
运行结果:
c++版代码参考:
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);
}
参考链接:
下一篇: SparkSQL