我正在尝试建立验证系统,以指出两个扫描的传单之间的区别。
我模糊了这两个图像,找到了单应性以对齐两个图像,然后发现了两个图像之间的差异以绘制矩形。
import cv2
import numpy as np
from skimage.measure import compare_ssim as ssim
from scipy import ndimage
#MAX_MATCHES = 1000000 #MSE for labels
MAX_MATCHES = 50000 #MSE for text
GOOD_MATCH_PERCENT = 0.4
def mse(imageA, imageB):
# the 'Mean Squared Error' between the two images is the
# sum of the squared difference between the two images;
# NOTE: the two images must have the same dimension
err = np.sum((imageA.astype("float") - imageB.astype("float")) ** 2)
err /= float(imageA.shape[0] * imageA.shape[1])
return err
# return the MSE, the lower the error, the more "similar"
# the two images are
def diff_remove_bg(img0, img, img1):
d1 = diff(img0, img)
d2 = diff(img, img1)
return cv2.bitwise_and(d1, d2)
def alignImages(im1, im2):
# Convert images to grayscale
im1Gray = cv2.cvtColor(im1, cv2.COLOR_BGR2GRAY)
im2Gray = cv2.cvtColor(im2, cv2.COLOR_BGR2GRAY)
# Detect ORB features and compute descriptors.
orb = cv2.ORB_create(MAX_MATCHES)
keypoints1, descriptors1 = orb.detectAndCompute(im1Gray, None)
keypoints2, descriptors2 = orb.detectAndCompute(im2Gray, None)
# Match features.
matcher = cv2.DescriptorMatcher_create(cv2.DESCRIPTOR_MATCHER_BRUTEFORCE_HAMMING)
matches = matcher.match(descriptors1, descriptors2, None)
# Sort matches by score
matches.sort(key=lambda x: x.distance, reverse=False)
# Remove not so good matches
numGoodMatches = int(len(matches) * GOOD_MATCH_PERCENT)
matches = matches[:numGoodMatches]
# Draw top matches
imMatches = cv2.drawMatches(im1, keypoints1, im2, keypoints2, matches, None)
cv2.imwrite("matches.png", imMatches)
# Extract location of good matches
points1 = np.zeros((len(matches), 2), dtype=np.float32)
points2 = np.zeros((len(matches), 2), dtype=np.float32)
for i, match in enumerate(matches):
points1[i, :] = keypoints1[match.queryIdx].pt
points2[i, :] = keypoints2[match.trainIdx].pt
# Find homography
h, mask = cv2.findHomography(points1, points2, cv2.RANSAC)
# Use homography
height, width, channels = im2.shape
im1Reg = cv2.warpPerspective(im1, h, (width, height))
return im1Reg, h
# Read reference image
refFilename = "standard.png"
print("Reading reference image : ", refFilename)
imReference = cv2.imread(refFilename, cv2.IMREAD_COLOR)
imReference = ndimage.gaussian_filter(imReference, 2)
imFilename = "sample-fin.png"
print("Reading image to align : ", imFilename);
im = cv2.imread(imFilename, cv2.IMREAD_COLOR)
im = ndimage.gaussian_filter(im, 2)
print("Aligning images ...")
# Registered image will be resotred in imReg.
# The estimated homography will be stored in h.
imReg, h = alignImages(im, imReference)
# Write aligned image to disk.
outFilename = "aligned.png"
print("Saving aligned image : ", outFilename);
cv2.imwrite(outFilename, imReg)
# Print estimated homography
print("Estimated homography : \n", h)
x1 = imReg
x2 = imReference
absdiff = cv2.absdiff(x1, x2)
print(np.max(absdiff))
#Threshold for minimum detection
threshold = absdiff < 30
absdiff[threshold] = 0
cv2.imwrite("absdiff.png", absdiff)
diff = cv2.subtract(x1, x2)
result = not np.any(diff)
########### Drawing Rectangles around the differences ##############
img = cv2.pyrDown(cv2.imread('absdiff.png', cv2.IMREAD_UNCHANGED))
img1 = cv2.pyrDown(cv2.imread('aligned.png', cv2.IMREAD_UNCHANGED))
ret, threshed_img = cv2.threshold(cv2.cvtColor(img, cv2.COLOR_BGR2GRAY),
40, 40, cv2.THRESH_BINARY)
_,contours, hier = cv2.findContours(threshed_img, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
for c in contours:
x,y,w,h = cv2.boundingRect(c)
cv2.rectangle(img1, (x-5, y-5), (x+w+10, y+h+10), (0, 255, 0), 2)
# get the min area rect
rect = cv2.minAreaRect(c)
box = cv2.boxPoints(rect)
# convert all coordinates floating point values to int
box = np.int0(box)
print(len(contours))
cv2.imwrite("cont-1.png", img1)
指出的错误:https://ibb.co/YWKxYLF
我想提高此算法的准确性。还是有其他方法可以用来解决这一任务?
编辑: 我想删除传单末尾出现的多余矩形。单应性也不是完美的。我必须在差异上设置一个巨大的门槛才能获得此结果。