比较两个不同的图像并找出差异
Compare two different images and find the differences
我有一个网络摄像头,可以拍摄混凝土板的照片。现在我想检查平板上是否有物体。对象可以是任何东西,因此不能在 class 中枚举。不幸的是,我无法将网络摄像头图像直接与混凝土板上没有物体的图像进行比较,因为摄像头图像在 x 和 y 方向上的偏移可能很小,而且照明也不总是相同。所以我不能使用 cv2.substract
。
我更喜欢前景和背景减法,其中背景只是我的混凝土板,前景是物体。但是由于物体不移动而是静止在平板上,我也不能使用 cv2.createBackgroundSubtractorMOG2()
。
图片是这样的:
没有任何物体的混凝土拍击:
对象的耳光:
在Python/OpenCV中,您可以进行除法归一化以均匀照明并使背景变白。然后做你的减法。然后使用形态学清理小区域。然后找到轮廓并丢弃由于划分归一化和形态学后留下的噪声引起的任何小区域。
下面是除法归一化的方法。
输入 1:
输入 2:
import cv2
import numpy as np
# load image
img1 = cv2.imread("img1.jpg")
img2 = cv2.imread("img2.jpg")
# convert to grayscale
gray1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
gray2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)
# blur
blur1 = cv2.GaussianBlur(gray1, (0,0), sigmaX=13, sigmaY=13)
blur2 = cv2.GaussianBlur(gray2, (0,0), sigmaX=13, sigmaY=13)
# divide
divide1 = cv2.divide(gray1, blur1, scale=255)
divide2 = cv2.divide(gray2, blur2, scale=255)
# threshold
thresh1 = cv2.threshold(divide1, 200, 255, cv2.THRESH_BINARY)[1]
thresh2 = cv2.threshold(divide2, 200, 255, cv2.THRESH_BINARY)[1]
# morphology
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3,3))
morph1 = cv2.morphologyEx(thresh1, cv2.MORPH_OPEN, kernel)
morph2 = cv2.morphologyEx(thresh2, cv2.MORPH_OPEN, kernel)
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5,5))
morph1 = cv2.morphologyEx(morph1, cv2.MORPH_CLOSE, kernel)
morph2 = cv2.morphologyEx(morph2, cv2.MORPH_CLOSE, kernel)
# write result to disk
cv2.imwrite("img1_division_normalize.jpg", divide1)
cv2.imwrite("img2_division_normalize.jpg", divide2)
cv2.imwrite("img1_division_morph1.jpg", morph1)
cv2.imwrite("img1_division_morph2.jpg", morph2)
# display it
cv2.imshow("img1_norm", divide1)
cv2.imshow("img2_norm", divide2)
cv2.imshow("img1_thresh", thresh1)
cv2.imshow("img2_thresh", thresh2)
cv2.imshow("img1_morph", morph1)
cv2.imshow("img2_morph", morph2)
cv2.waitKey(0)
cv2.destroyAllWindows()
图像 1 归一化:
图像 2 归一化:
图像 1 阈值化和形态清理:
图像 2 阈值化和形态清理:
在这种情况下,图像 1 变成全白。所以它(和减法)并不是真正需要的。您只需要为第二个图像结果找到轮廓,并在必要时逐个丢弃微小区域。剩下的就是你的对象了。
我有一个网络摄像头,可以拍摄混凝土板的照片。现在我想检查平板上是否有物体。对象可以是任何东西,因此不能在 class 中枚举。不幸的是,我无法将网络摄像头图像直接与混凝土板上没有物体的图像进行比较,因为摄像头图像在 x 和 y 方向上的偏移可能很小,而且照明也不总是相同。所以我不能使用 cv2.substract
。
我更喜欢前景和背景减法,其中背景只是我的混凝土板,前景是物体。但是由于物体不移动而是静止在平板上,我也不能使用 cv2.createBackgroundSubtractorMOG2()
。
图片是这样的:
没有任何物体的混凝土拍击:
对象的耳光:
在Python/OpenCV中,您可以进行除法归一化以均匀照明并使背景变白。然后做你的减法。然后使用形态学清理小区域。然后找到轮廓并丢弃由于划分归一化和形态学后留下的噪声引起的任何小区域。
下面是除法归一化的方法。
输入 1:
输入 2:
import cv2
import numpy as np
# load image
img1 = cv2.imread("img1.jpg")
img2 = cv2.imread("img2.jpg")
# convert to grayscale
gray1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
gray2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)
# blur
blur1 = cv2.GaussianBlur(gray1, (0,0), sigmaX=13, sigmaY=13)
blur2 = cv2.GaussianBlur(gray2, (0,0), sigmaX=13, sigmaY=13)
# divide
divide1 = cv2.divide(gray1, blur1, scale=255)
divide2 = cv2.divide(gray2, blur2, scale=255)
# threshold
thresh1 = cv2.threshold(divide1, 200, 255, cv2.THRESH_BINARY)[1]
thresh2 = cv2.threshold(divide2, 200, 255, cv2.THRESH_BINARY)[1]
# morphology
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3,3))
morph1 = cv2.morphologyEx(thresh1, cv2.MORPH_OPEN, kernel)
morph2 = cv2.morphologyEx(thresh2, cv2.MORPH_OPEN, kernel)
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5,5))
morph1 = cv2.morphologyEx(morph1, cv2.MORPH_CLOSE, kernel)
morph2 = cv2.morphologyEx(morph2, cv2.MORPH_CLOSE, kernel)
# write result to disk
cv2.imwrite("img1_division_normalize.jpg", divide1)
cv2.imwrite("img2_division_normalize.jpg", divide2)
cv2.imwrite("img1_division_morph1.jpg", morph1)
cv2.imwrite("img1_division_morph2.jpg", morph2)
# display it
cv2.imshow("img1_norm", divide1)
cv2.imshow("img2_norm", divide2)
cv2.imshow("img1_thresh", thresh1)
cv2.imshow("img2_thresh", thresh2)
cv2.imshow("img1_morph", morph1)
cv2.imshow("img2_morph", morph2)
cv2.waitKey(0)
cv2.destroyAllWindows()
图像 1 归一化:
图像 2 归一化:
图像 1 阈值化和形态清理:
图像 2 阈值化和形态清理:
在这种情况下,图像 1 变成全白。所以它(和减法)并不是真正需要的。您只需要为第二个图像结果找到轮廓,并在必要时逐个丢弃微小区域。剩下的就是你的对象了。