图像比较不适用于相机拍摄的图像
Image Comparison not working with Camera captured images
[![在此处输入图片描述][1]][1][![在此处输入图片描述][2]][2]我正在比较两张图片的差异。
问题是当我从网上下载一些图像时它工作正常,但当我试图比较从 Phone 相机捕获的图像时它不起作用。知道我哪里做错了吗?
我在 Google Colab 工作。我尝试使用 'structural_similarity' 和 dilate
以及 findContours
方法,两者都不适用于相机图像。
我尝试使用模板匹配,然后对齐图像,然后尝试捕捉差异,但仍然得到相同的结果。
正如您在图片中看到的那样 - 它显示了所有 nits n 位的差异,但没有显示更大的对象作为差异。
Phone 捕获的图像 1:
Phone 截图2:
这是我的代码:
import cv2
from skimage.metrics import structural_similarity
import imutils
ref = cv2.imread('/content/drive/My Drive/Image Comparison/1.png')
target = cv2.imread('/content/drive/My Drive/Image Comparison/2.png')
gray_ref = cv2.cvtColor(ref, cv2.COLOR_BGR2GRAY)
gray_compare = cv2.cvtColor(target, cv2.COLOR_BGR2GRAY)
(score, diff) = structural_similarity(gray_ref,gray_compare, full=True)
diff = (diff * 255).astype("uint8")
thresh = cv2.threshold(diff, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)[1]
contours = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contours = imutils.grab_contours(contours)
no_of_differences = 0
for c in contours:
(x, y, w, h) = cv2.boundingRect(c)
rect_area = w*h
if rect_area > 10:
no_of_differences +=1
cv2.rectangle(ref, (x, y), (x + w, y + h), (0, 0, 255), 2)
cv2.rectangle(target, (x, y), (x + w, y + h), (0, 0, 255), 2)
print("# of differences = ", no_of_differences)
scale_percent = 60 # percent of original size
width = int(ref.shape[1] * scale_percent / 100)
height = int(target.shape[0] * scale_percent / 100)
dim = (width, height)
# resize image
resized_ref = cv2.resize(ref, dim, interpolation = cv2.INTER_AREA)
resized_target = cv2.resize(target, dim, interpolation = cv2.INTER_AREA)
cv2_imshow(resized_ref)
cv2_imshow(resized_target)
cv2.waitKey(0)
您的解决方案存在两个主要问题:
structural_similarity
returns 正值和负值(范围 [-1, 1])。
转换:diff = (diff * 255).astype("uint8")
适用范围 [0, 1],但对于范围 [-1, 1],我们可以使用以下转换:
diff = ((diff+1) * 127.5).astype("uint8") # Convert from range [-1, 1] to [0, 255].
使用具有自动阈值 cv2.THRESH_OTSU
的 cv2.threshold
不足以对图像进行阈值处理(至少在 structural_similarity
之后应用时)。
我们可以将其替换为 adaptiveThreshold - 自适应高斯阈值。
(我建议的解决方案仍然不是最优的,因为我必须手动调整参数,但找到一个通用的解决方案似乎太难了)。
将 thresh = cv2.threshold(diff, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)[1]
替换为:
thresh = cv2.adaptiveThreshold(diff, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 175, 30) # Use adaptive gaussian threshold instead of cv2.THRESH_OTSU
代码示例(不使用 Google Colb):
import cv2
from skimage.metrics import structural_similarity
import imutils
ref = cv2.imread('1.png')
target = cv2.imread('2.png')
ref = ref[(ref.shape[0]-480):(ref.shape[0]+480), (ref.shape[1]-768):(ref.shape[1]+768), :]
target = target[(target.shape[0]-480):(target.shape[0]+480), (target.shape[1]-768):(target.shape[1]+768), :]
gray_ref = cv2.cvtColor(ref, cv2.COLOR_BGR2GRAY)
gray_compare = cv2.cvtColor(target, cv2.COLOR_BGR2GRAY)
(score, diff) = structural_similarity(gray_ref, gray_compare, full=True)
#diff = (diff * 255).astype("uint8")
diff = ((diff+1) * 127.5).astype("uint8") # Support negative values (range of diff is [-1, 1])
#thresh = cv2.threshold(diff, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)[1]
thresh = cv2.adaptiveThreshold(diff, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 175, 30) # Use adaptive gaussian threshold instead of cv2.THRESH_OTSU
contours = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contours = imutils.grab_contours(contours)
no_of_differences = 0
for c in contours:
(x, y, w, h) = cv2.boundingRect(c)
rect_area = w*h
if rect_area > 10:
no_of_differences +=1
cv2.rectangle(ref, (x, y), (x + w, y + h), (0, 0, 255), 2)
cv2.rectangle(target, (x, y), (x + w, y + h), (0, 0, 255), 2)
print("# of differences = ", no_of_differences)
scale_percent = 60 # percent of original size
width = int(ref.shape[1] * scale_percent / 100)
height = int(target.shape[0] * scale_percent / 100)
dim = (width, height)
# resize image
resized_ref = cv2.resize(ref, dim, interpolation = cv2.INTER_AREA)
resized_target = cv2.resize(target, dim, interpolation = cv2.INTER_AREA)
cv2.imshow('diff', diff)
cv2.imshow('thresh', thresh)
cv2.imshow('resized_ref', resized_ref)
cv2.imshow('resized_target', resized_target)
cv2.waitKey()
cv2.destroyAllWindows()
原文diff = (diff * 255).astype("uint8")
:
可以看到,有数据溢出。
diff = ((diff+1) * 127.5).astype("uint8")
:
原文thresh = cv2.threshold(diff, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)[1]
:
如您所见,thresh
的一半左右是白色的。
thresh = cv2.adaptiveThreshold(diff, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 175, 30)
的结果:
resized_target
:
resized_ref
:
备注:
您 post 编辑的图像包含标记,但大小不同。
下次,尝试 post 清理图像而不是屏幕截图...
[![在此处输入图片描述][1]][1][![在此处输入图片描述][2]][2]我正在比较两张图片的差异。
问题是当我从网上下载一些图像时它工作正常,但当我试图比较从 Phone 相机捕获的图像时它不起作用。知道我哪里做错了吗?
我在 Google Colab 工作。我尝试使用 'structural_similarity' 和 dilate
以及 findContours
方法,两者都不适用于相机图像。
我尝试使用模板匹配,然后对齐图像,然后尝试捕捉差异,但仍然得到相同的结果。
正如您在图片中看到的那样 - 它显示了所有 nits n 位的差异,但没有显示更大的对象作为差异。
Phone 捕获的图像 1:
Phone 截图2:
这是我的代码:
import cv2
from skimage.metrics import structural_similarity
import imutils
ref = cv2.imread('/content/drive/My Drive/Image Comparison/1.png')
target = cv2.imread('/content/drive/My Drive/Image Comparison/2.png')
gray_ref = cv2.cvtColor(ref, cv2.COLOR_BGR2GRAY)
gray_compare = cv2.cvtColor(target, cv2.COLOR_BGR2GRAY)
(score, diff) = structural_similarity(gray_ref,gray_compare, full=True)
diff = (diff * 255).astype("uint8")
thresh = cv2.threshold(diff, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)[1]
contours = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contours = imutils.grab_contours(contours)
no_of_differences = 0
for c in contours:
(x, y, w, h) = cv2.boundingRect(c)
rect_area = w*h
if rect_area > 10:
no_of_differences +=1
cv2.rectangle(ref, (x, y), (x + w, y + h), (0, 0, 255), 2)
cv2.rectangle(target, (x, y), (x + w, y + h), (0, 0, 255), 2)
print("# of differences = ", no_of_differences)
scale_percent = 60 # percent of original size
width = int(ref.shape[1] * scale_percent / 100)
height = int(target.shape[0] * scale_percent / 100)
dim = (width, height)
# resize image
resized_ref = cv2.resize(ref, dim, interpolation = cv2.INTER_AREA)
resized_target = cv2.resize(target, dim, interpolation = cv2.INTER_AREA)
cv2_imshow(resized_ref)
cv2_imshow(resized_target)
cv2.waitKey(0)
您的解决方案存在两个主要问题:
structural_similarity
returns 正值和负值(范围 [-1, 1])。
转换:diff = (diff * 255).astype("uint8")
适用范围 [0, 1],但对于范围 [-1, 1],我们可以使用以下转换:diff = ((diff+1) * 127.5).astype("uint8") # Convert from range [-1, 1] to [0, 255].
使用具有自动阈值
cv2.THRESH_OTSU
的cv2.threshold
不足以对图像进行阈值处理(至少在structural_similarity
之后应用时)。
我们可以将其替换为 adaptiveThreshold - 自适应高斯阈值。
(我建议的解决方案仍然不是最优的,因为我必须手动调整参数,但找到一个通用的解决方案似乎太难了)。
将thresh = cv2.threshold(diff, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)[1]
替换为:thresh = cv2.adaptiveThreshold(diff, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 175, 30) # Use adaptive gaussian threshold instead of cv2.THRESH_OTSU
代码示例(不使用 Google Colb):
import cv2
from skimage.metrics import structural_similarity
import imutils
ref = cv2.imread('1.png')
target = cv2.imread('2.png')
ref = ref[(ref.shape[0]-480):(ref.shape[0]+480), (ref.shape[1]-768):(ref.shape[1]+768), :]
target = target[(target.shape[0]-480):(target.shape[0]+480), (target.shape[1]-768):(target.shape[1]+768), :]
gray_ref = cv2.cvtColor(ref, cv2.COLOR_BGR2GRAY)
gray_compare = cv2.cvtColor(target, cv2.COLOR_BGR2GRAY)
(score, diff) = structural_similarity(gray_ref, gray_compare, full=True)
#diff = (diff * 255).astype("uint8")
diff = ((diff+1) * 127.5).astype("uint8") # Support negative values (range of diff is [-1, 1])
#thresh = cv2.threshold(diff, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)[1]
thresh = cv2.adaptiveThreshold(diff, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 175, 30) # Use adaptive gaussian threshold instead of cv2.THRESH_OTSU
contours = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contours = imutils.grab_contours(contours)
no_of_differences = 0
for c in contours:
(x, y, w, h) = cv2.boundingRect(c)
rect_area = w*h
if rect_area > 10:
no_of_differences +=1
cv2.rectangle(ref, (x, y), (x + w, y + h), (0, 0, 255), 2)
cv2.rectangle(target, (x, y), (x + w, y + h), (0, 0, 255), 2)
print("# of differences = ", no_of_differences)
scale_percent = 60 # percent of original size
width = int(ref.shape[1] * scale_percent / 100)
height = int(target.shape[0] * scale_percent / 100)
dim = (width, height)
# resize image
resized_ref = cv2.resize(ref, dim, interpolation = cv2.INTER_AREA)
resized_target = cv2.resize(target, dim, interpolation = cv2.INTER_AREA)
cv2.imshow('diff', diff)
cv2.imshow('thresh', thresh)
cv2.imshow('resized_ref', resized_ref)
cv2.imshow('resized_target', resized_target)
cv2.waitKey()
cv2.destroyAllWindows()
原文diff = (diff * 255).astype("uint8")
:
可以看到,有数据溢出。
diff = ((diff+1) * 127.5).astype("uint8")
:
原文thresh = cv2.threshold(diff, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)[1]
:
thresh
的一半左右是白色的。
thresh = cv2.adaptiveThreshold(diff, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 175, 30)
的结果:
resized_target
:
resized_ref
:
备注:
您 post 编辑的图像包含标记,但大小不同。
下次,尝试 post 清理图像而不是屏幕截图...