Deskewing scanned image to match original image using OpenCV and SIFT/SURF(使用 OpenCV 和 SIFT/SURF 校正扫描图像以匹配原始图像)
问题描述
我有一个数字形式的原始页面和同一页面的多个扫描版本.我的目标是对扫描的页面进行纠偏,使其尽可能与原始页面匹配.我知道我可以使用
原来我非常接近解决自己的问题.这是我的代码的工作版本:
将 numpy 导入为 np导入简历2从 matplotlib 导入 pyplot 作为 plt导入数学def 纠偏():im_out = cv2.warpPerspective(skewed_image, np.linalg.inv(M), (orig_image.shape[1], orig_image.shape[0]))plt.imshow(im_out, '灰色')plt.show()orig_image = cv2.imread(r'image.png', 0)skewed_image = cv2.imread(r'imageSkewed.png', 0)冲浪 = cv2.xfeatures2d.SURF_create(400)kp1, des1 = surf.detectAndCompute(orig_image, None)kp2, des2 = surf.detectAndCompute(skewed_image, 无)FLANN_INDEX_KDTREE = 0index_params = dict(算法=FLANN_INDEX_KDTREE,树=5)search_params = dict(检查=50)flann = cv2.FlannBasedMatcher(index_params, search_params)匹配 = flann.knnMatch(des1, des2, k=2)# 根据劳氏比率测试存储所有好的匹配.好=[]对于 m,n 匹配:如果 m.distance <0.7 * n.距离:好.追加(米)MIN_MATCH_COUNT = 10如果 len(good) >MIN_MATCH_COUNT 个:src_pts = np.float32([kp1[m.queryIdx].pt for m in good]).reshape(-1, 1, 2)dst_pts = np.float32([kp2[m.trainIdx].pt for m in good]).reshape(-1, 1, 2)M, 掩码 = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC, 5.0)# 详见 https://ch.mathworks.com/help/images/examples/find-image-rotation-and-scale-using-automated-feature-matching.htmlss = M[0, 1]sc = M[0, 0]scaleRecovered = math.sqrt(ss * ss + sc * sc)thetaRecovered = math.atan2(ss, sc) * 180/math.piprint("计算的比例差:%.2f
计算的旋转差:%.2f" % (scaleRecovered, thetaRecovered))纠偏()别的:print("没有找到足够的匹配 - %d/%d" % (len(good), MIN_MATCH_COUNT))匹配掩码 = 无I have an original page in digital form and several scanned versions of the same page. My goal is to deskew the scanned pages such that they match the original page as much as possible. I know that I could use the Probabilistic Hough Transform as described here for fixing the rotation but the scanned papers also differ in size as some people scaled the page to a different paper format. I think that the findHomography() function in OpenCV in combination with the keypoints from SIFT/SURF are exactly what I need to solve this problem. However, I just can't get my deskew() function to work.
Most of my code stems from the following two sources: http://www.learnopencv.com/homography-examples-using-opencv-python-c/ and http://docs.opencv.org/3.1.0/d1/de0/tutorial_py_feature_homography.html.
import numpy as np
import cv2
from matplotlib import pyplot as plt
# FIXME: doesn't work
def deskew():
im_out = cv2.warpPerspective(img1, M, (img2.shape[1], img2.shape[0]))
plt.imshow(im_out, 'gray')
plt.show()
# resizing images to improve speed
factor = 0.4
img1 = cv2.resize(cv2.imread("image.png", 0), None, fx=factor, fy=factor, interpolation=cv2.INTER_CUBIC)
img2 = cv2.resize(cv2.imread("imageSkewed.png", 0), None, fx=factor, fy=factor, interpolation=cv2.INTER_CUBIC)
surf = cv2.xfeatures2d.SURF_create()
kp1, des1 = surf.detectAndCompute(img1, None)
kp2, des2 = surf.detectAndCompute(img2, None)
FLANN_INDEX_KDTREE = 0
index_params = dict(algorithm=FLANN_INDEX_KDTREE, trees=5)
search_params = dict(checks=50)
flann = cv2.FlannBasedMatcher(index_params, search_params)
matches = flann.knnMatch(des1, des2, k=2)
# store all the good matches as per Lowe's ratio test.
good = []
for m, n in matches:
if m.distance < 0.7 * n.distance:
good.append(m)
MIN_MATCH_COUNT = 10
if len(good) > MIN_MATCH_COUNT:
src_pts = np.float32([kp1[m.queryIdx].pt for m in good
]).reshape(-1, 1, 2)
dst_pts = np.float32([kp2[m.trainIdx].pt for m in good
]).reshape(-1, 1, 2)
M, mask = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC, 5.0)
matchesMask = mask.ravel().tolist()
h, w = img1.shape
pts = np.float32([[0, 0], [0, h - 1], [w - 1, h - 1], [w - 1, 0]]).reshape(-1, 1, 2)
dst = cv2.perspectiveTransform(pts, M)
deskew()
img2 = cv2.polylines(img2, [np.int32(dst)], True, 255, 3, cv2.LINE_AA)
else:
print("Not enough matches are found - %d/%d" % (len(good), MIN_MATCH_COUNT))
matchesMask = None
# show matching keypoints
draw_params = dict(matchColor=(0, 255, 0), # draw matches in green color
singlePointColor=None,
matchesMask=matchesMask, # draw only inliers
flags=2)
img3 = cv2.drawMatches(img1, kp1, img2, kp2, good, None, **draw_params)
plt.imshow(img3, 'gray')
plt.show()
Turns out I was very close to solving my own problem. Here's the working version of my code:
import numpy as np
import cv2
from matplotlib import pyplot as plt
import math
def deskew():
im_out = cv2.warpPerspective(skewed_image, np.linalg.inv(M), (orig_image.shape[1], orig_image.shape[0]))
plt.imshow(im_out, 'gray')
plt.show()
orig_image = cv2.imread(r'image.png', 0)
skewed_image = cv2.imread(r'imageSkewed.png', 0)
surf = cv2.xfeatures2d.SURF_create(400)
kp1, des1 = surf.detectAndCompute(orig_image, None)
kp2, des2 = surf.detectAndCompute(skewed_image, None)
FLANN_INDEX_KDTREE = 0
index_params = dict(algorithm=FLANN_INDEX_KDTREE, trees=5)
search_params = dict(checks=50)
flann = cv2.FlannBasedMatcher(index_params, search_params)
matches = flann.knnMatch(des1, des2, k=2)
# store all the good matches as per Lowe's ratio test.
good = []
for m, n in matches:
if m.distance < 0.7 * n.distance:
good.append(m)
MIN_MATCH_COUNT = 10
if len(good) > MIN_MATCH_COUNT:
src_pts = np.float32([kp1[m.queryIdx].pt for m in good
]).reshape(-1, 1, 2)
dst_pts = np.float32([kp2[m.trainIdx].pt for m in good
]).reshape(-1, 1, 2)
M, mask = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC, 5.0)
# see https://ch.mathworks.com/help/images/examples/find-image-rotation-and-scale-using-automated-feature-matching.html for details
ss = M[0, 1]
sc = M[0, 0]
scaleRecovered = math.sqrt(ss * ss + sc * sc)
thetaRecovered = math.atan2(ss, sc) * 180 / math.pi
print("Calculated scale difference: %.2f
Calculated rotation difference: %.2f" % (scaleRecovered, thetaRecovered))
deskew()
else:
print("Not enough matches are found - %d/%d" % (len(good), MIN_MATCH_COUNT))
matchesMask = None
这篇关于使用 OpenCV 和 SIFT/SURF 校正扫描图像以匹配原始图像的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:使用 OpenCV 和 SIFT/SURF 校正扫描图像以匹配原始图
基础教程推荐
- pyserial - 可以从线程 a 写入串行端口,是否阻塞从线程 b 读取? 2022-01-01
- 将 x 轴刻度更改为自定义字符串 2022-01-01
- 用 Python 编写 Fortran 无格式文件 2022-01-01
- numpy float:比算术运算中内置的慢 10 倍? 2022-01-01
- 在 Celery 工作人员中捕获 Heroku SIGTERM 以优雅地关 2022-01-01
- 尝试制作WhatsApp机器人 2022-01-01
- 与常规 dict 相比,Python manager.dict() 非常慢 2022-01-01
- 使用生成器和迭代器时 Python 多循环失败 2022-01-01
- 由Python将MP3转换为MIDI(类型错误:无法加载插件:mtg-Melodia:Melodia) 2022-01-01
- Discord.py 缺少必需的参数 2022-01-01
