在OpenCV Python中检测/提取图像之间的最大差异
我正在做一个射击模拟器项目,我必须从图像中检测弹孔。我正在尝试区分两幅图像,这样我就可以在图像之间检测到新的洞,但它没有按预期工作。在这两幅图像之间,由于相机帧之间的轻微移动,先前的弹孔中有微小的变化 我的第一张照片在这里 before.png 第二个在这里 after.png 我尝试了这个代码来检查差异在OpenCV Python中检测/提取图像之间的最大差异,python,opencv,image-processing,Python,Opencv,Image Processing,我正在做一个射击模拟器项目,我必须从图像中检测弹孔。我正在尝试区分两幅图像,这样我就可以在图像之间检测到新的洞,但它没有按预期工作。在这两幅图像之间,由于相机帧之间的轻微移动,先前的弹孔中有微小的变化 我的第一张照片在这里 before.png 第二个在这里 after.png 我尝试了这个代码来检查差异 导入cv2 将numpy作为np导入 before=cv2.imread(“before.png”)after=cv2.imread(“after.png”) 结果=之后-之前 cv2.i
导入cv2
将numpy作为np导入
before=cv2.imread(“before.png”)after=cv2.imread(“after.png”)
结果=之后-之前
cv2.imwrite(“result.png”,result)
我在result.png中得到的结果是下图
result.png
但这不是我所期望的,我只想探测新的洞
但它显示的是与前一幅图像的一些像素的差异。
我期待的结果是
expected.png
请帮我弄清楚,这样它只能检测出很大的差异
提前谢谢
任何新想法都将受到欢迎。为了找出两幅图像之间的差异,您可以利用中引入的结构相似性指数(SSIM)。此方法已在图像处理库中实现。您可以使用
pip install scikit image
安装scikit image
使用scikit图像中的compare_ssim()
函数,它返回一个score
和一个差分图像diff
。得分
表示两个输入图像之间的结构相似性指数,可以在[-1,1]范围内,数值更接近表示更高相似性的数值。但是,由于您只对两个图像的不同之处感兴趣,因此diff
图像就是您要查找的内容。diff
图像包含两个图像之间的实际图像差异
接下来,我们使用cv2.findContours()
查找所有轮廓,并过滤最大轮廓。最大轮廓应代表新检测到的差异,因为微小差异应小于添加的项目符号
这是两幅图像之间检测到的最大差异
这是两幅图像之间的实际差异。注意所有的差异是如何被捕捉到的,但由于新的子弹很可能是最大的轮廓,我们可以过滤掉相机帧之间的所有其他轻微移动。
注意:如果我们假设新子弹在diff
图像中具有最大的轮廓,则此方法非常有效。如果最新的孔较小,则可能必须遮罩现有区域,以及新图像中的任何新轮廓都将是新孔(假设图像将是带白孔的均匀黑色背景)
下面是另一个具有不同输入图像的示例。SSIM非常适合检测图像之间的差异
这是我的方法:在我们从另一个中减去一个之后,仍然有一些噪声,所以我只是尝试去除这些噪声。我将图像按大小的百分位数进行分割,并对图像的每个小部分进行前后比较,以便只剩下大量的白色像素。当存在遮挡时,即当新快照与现有快照重叠时,该算法缺乏精度
import cv2
import numpy as np
# This is the percentage of the width/height we're gonna cut
# 0.99 < percent < 0.1
percent = 0.01
before = cv2.imread("before.png")
after = cv2.imread("after.png")
result = after - before # Here, we eliminate the biggest differences between before and after
h, w, _ = result.shape
hPercent = percent * h
wPercent = percent * w
def isBlack(crop): # Function that tells if the crop is black
mask = np.zeros(crop.shape, dtype = int)
return not (np.bitwise_or(crop, mask)).any()
for wFrom in range(0, w, int(wPercent)): # Here we are gonna remove that noise
for hFrom in range(0, h, int(hPercent)):
wTo = int(wFrom+wPercent)
hTo = int(hFrom+hPercent)
crop = result[wFrom:wTo,hFrom:hTo] # Crop the image
if isBlack(crop): # If it is black, there is no shot in it
continue # We dont need to continue with the algorithm
beforeCrop = before[wFrom:wTo,hFrom:hTo] # Crop the image before
if not isBlack(beforeCrop): # If the image before is not black, it means there was a hot already there
result[wFrom:wTo,hFrom:hTo] = [0, 0, 0] # So, we erase it from the result
cv2.imshow("result",result )
cv2.imshow("before", before)
cv2.imshow("after", after)
cv2.waitKey(0)
导入cv2
将numpy作为np导入
#这是我们要切割的宽度/高度的百分比
#0.99<百分之<0.1
百分比=0.01
before=cv2.imread(“before.png”)
after=cv2.imread(“after.png”)
结果=之后-之前#在这里,我们消除了之前和之后的最大差异
h、 w,u=result.shape
h百分比=百分比*h
wPercent=百分比*w
def isBlack(裁剪):用于告知裁剪是否为黑色的函数
掩码=np.zero(crop.shape,dtype=int)
返回not(np.按位_或(裁剪、掩码)).any()
对于范围(0,w,int(wPercent))内的wFrom:#这里我们将消除该噪声
对于范围(0,h,int(hPercent))内的hFrom:
wTo=int(wFrom+W百分比)
hTo=int(hFrom+hPercent)
裁剪=结果[wFrom:wTo,hFrom:hTo]#裁剪图像
如果是黑色(作物):#如果是黑色,则没有子弹
继续,我们不需要继续算法
beforeCrop=before[wFrom:wTo,hFrom:hTo]#在之前裁剪图像
如果不是黑色(在裁剪之前):#如果之前的图像不是黑色,则表示那里已经有热图像
结果[wFrom:wTo,hFrom:hTo]=[0,0,0]#因此,我们将其从结果中删除
cv2.imshow(“结果”,结果)
cv2.imshow(“之前”,之前)
cv2.imshow(“之后”,之后)
cv2.等待键(0)
如您所见,它适用于您提供的用例。好的下一步是保留快照位置数组,以便您可以我的代码:
来自skimage.measure导入比较
导入argparse
导入imutils
进口cv2
将numpy作为np导入
#加载两个输入图像
imageA=cv2.imread('./Input_1.png')
cv2.imwrite(“./org.jpg”,imageA)
#imageA=cv2.medianBlur(imageA,29)
imageB=cv2.imread('./Input_2.png')
cv2.imwrite(“./test.jpg”,imageB)
#imageB=cv2.medianBlur(imageB,29)
#将图像转换为灰度
灰度A=cv2.CVT颜色(图像A,cv2.COLOR\U BGR2GRAY)
grayB=cv2.CVT颜色(图像B,cv2.COLOR\u BGR2GRAY)
##########################################################################################################
差值=cv2。减去(灰度A、灰度B)
结果=非np.任何(差异)
如果结果为真:
打印(“图片相同”)
其他:
cv2.imwrite(“./open\u cv\u subtract.jpg”,差值)
打印(“图片不同,差异被存储。”)
##########################################################################################################
diff=cv2.absdiff(灰度A、灰度B)
cv2.imwrite(“./tabsdiff.png”,
import cv2
import numpy as np
# This is the percentage of the width/height we're gonna cut
# 0.99 < percent < 0.1
percent = 0.01
before = cv2.imread("before.png")
after = cv2.imread("after.png")
result = after - before # Here, we eliminate the biggest differences between before and after
h, w, _ = result.shape
hPercent = percent * h
wPercent = percent * w
def isBlack(crop): # Function that tells if the crop is black
mask = np.zeros(crop.shape, dtype = int)
return not (np.bitwise_or(crop, mask)).any()
for wFrom in range(0, w, int(wPercent)): # Here we are gonna remove that noise
for hFrom in range(0, h, int(hPercent)):
wTo = int(wFrom+wPercent)
hTo = int(hFrom+hPercent)
crop = result[wFrom:wTo,hFrom:hTo] # Crop the image
if isBlack(crop): # If it is black, there is no shot in it
continue # We dont need to continue with the algorithm
beforeCrop = before[wFrom:wTo,hFrom:hTo] # Crop the image before
if not isBlack(beforeCrop): # If the image before is not black, it means there was a hot already there
result[wFrom:wTo,hFrom:hTo] = [0, 0, 0] # So, we erase it from the result
cv2.imshow("result",result )
cv2.imshow("before", before)
cv2.imshow("after", after)
cv2.waitKey(0)