Python OpenCV中模板匹配的分辨率操作
我试图使用模板匹配在给定的pdf文档中找到一个等式,该文档是由LaTeX生成的。当我重新使用代码时,当我从原始页面裁剪图片(转换为jpeg或png)时,我只能得到非常好的匹配,但是当我单独编译公式代码并生成jpg/png输出时,匹配出现了巨大的错误 我相信原因与分辨率有关,但由于我是该领域的业余爱好者,我无法合理地使由独立方程式生成的jpg在整个页面上具有与jpg相同的像素结构。以下是从上述OpenCV网站复制(或多或少)的代码,OpenCV是python的一个实现:Python OpenCV中模板匹配的分辨率操作,python,opencv,pdf,image-processing,resolution,Python,Opencv,Pdf,Image Processing,Resolution,我试图使用模板匹配在给定的pdf文档中找到一个等式,该文档是由LaTeX生成的。当我重新使用代码时,当我从原始页面裁剪图片(转换为jpeg或png)时,我只能得到非常好的匹配,但是当我单独编译公式代码并生成jpg/png输出时,匹配出现了巨大的错误 我相信原因与分辨率有关,但由于我是该领域的业余爱好者,我无法合理地使由独立方程式生成的jpg在整个页面上具有与jpg相同的像素结构。以下是从上述OpenCV网站复制(或多或少)的代码,OpenCV是python的一个实现: import cv2 fr
import cv2
from PIL import Image
img = cv2.imread('location of the original image', 0)
img2 = img.copy()
template = cv2.imread('location of the patch I look for',0)
w, h = template.shape[::-1]
# All the 6 methods for comparison in a list
methods = ['cv2.TM_CCOEFF', 'cv2.TM_CCOEFF_NORMED', 'cv2.TM_CCORR',
'cv2.TM_CCORR_NORMED', 'cv2.TM_SQDIFF', 'cv2.TM_SQDIFF_NORMED']
method = eval(methods[0])
# Apply template Matching
res = cv2.matchTemplate(img,template,method)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)
# If the method is TM_SQDIFF or TM_SQDIFF_NORMED, take minimum
if method in [cv2.TM_SQDIFF, cv2.TM_SQDIFF_NORMED]:
top_left = min_loc
else:
top_left = max_loc
bottom_right = (top_left[0] + w, top_left[1] + h)
print top_left, bottom_right
img = Image.open('location of the original image')
#cropping the original image with the found coordinates to make a qualitative comparison
cropped = img.crop((top_left[0], top_left[1], bottom_right[0], bottom_right[1]))
cropped.save('location to save the cropped image using the coordinates found by template matching')
以下是我寻找第一个方程式的示例页面:
生成特定独立方程式的代码如下所示:
\documentclass[preview]{standalone}
\usepackage{amsmath}
\begin{document}\begin{align*}
(\mu_1+\mu_2)(\emptyset) = \mu_1(\emptyset) + \mu_2(\emptyset) = 0 + 0 =0
\label{eq_0}
\end{align*}
\end{document}
我编译了它,然后在中使用或使用.image()方法修剪方程周围的空白。在原始页面上使用此修剪输出生成的模板匹配不会给出合理的结果。以下是使用pdfcrop/Mac的Preview.app进行修剪/转换的输出:
直接从上面的页面裁剪方程式效果很好。我希望得到一些解释和帮助
编辑:
我还发现了以下使用模板匹配的方法,通过使用不同的可能比例:
然而,由于我愿意处理多达1000个文档,因此这似乎是一种非常缓慢的方法。另外,我认为应该有一种更合乎逻辑的方法来处理它,通过某种方式找到相关的尺度。模板匹配的问题是,它只在非常受控的环境中工作。这意味着,如果从实际图像中获取模板,它将非常有效,但如果分辨率不同,或者即使图像稍微有点旋转,它也不起作用
我建议你找到另一种更适合这个问题的算法。在中,您可以找到一些针对您的问题的特定算法。模板匹配的问题是,它只在非常受控的环境中工作。这意味着,如果从实际图像中获取模板,它将非常有效,但如果分辨率不同,或者即使图像稍微有点旋转,它也不起作用
我建议你找到另一种更适合这个问题的算法。在中,您可以找到一些针对您的问题的特定算法。您可以使用模板匹配,即带有描述符的关键点。它们是缩放不变的,因此不需要迭代图像的不同缩放版本 python示例 OpenCV提供的可用于给定示例的ORB功能
python find_obj.py --feature=brisk rB4Yy_big.jpg ZjBAA.jpg
请注意,我没有使用公式的裁剪版本进行搜索,而是使用一个周围有一些白色像素的版本,因此关键点检测可以正常工作。它周围需要一些空间,因为关键点必须完全位于图像内部。否则,无法计算描述符
这张大图是你文章中的原作
另外一句话:你总是会得到一些匹配。如果您正在搜索的公式图像在大图像中不存在,则匹配将是无意义的。如果需要对这些误报进行分类,您可以选择以下选项:
- 检查结果es的平均距离是否足够小
- 检查是否可以计算出所需的时间
编辑:既然您要求,下面是一个版本,它围绕找到的公式而不是匹配项绘制边界框:
#!/usr/bin/env python
# Python 2/3 compatibility
from __future__ import print_function
import numpy as np
import cv2
def init_feature():
detector = cv2.BRISK_create()
norm = cv2.NORM_HAMMING
matcher = cv2.BFMatcher(norm)
return detector, matcher
def filter_matches(kp1, kp2, matches, ratio = 0.75):
mkp1, mkp2 = [], []
for m in matches:
if len(m) == 2 and m[0].distance < m[1].distance * ratio:
m = m[0]
mkp1.append( kp1[m.queryIdx] )
mkp2.append( kp2[m.trainIdx] )
p1 = np.float32([kp.pt for kp in mkp1])
p2 = np.float32([kp.pt for kp in mkp2])
kp_pairs = zip(mkp1, mkp2)
return p1, p2, kp_pairs
def explore_match(win, img1, img2, kp_pairs, status = None, H = None):
h1, w1 = img1.shape[:2]
h2, w2 = img2.shape[:2]
vis = np.zeros((max(h1, h2), w1+w2), np.uint8)
vis[:h1, :w1] = img1
vis[:h2, w1:w1+w2] = img2
vis = cv2.cvtColor(vis, cv2.COLOR_GRAY2BGR)
if H is not None:
corners = np.float32([[0, 0], [w1, 0], [w1, h1], [0, h1]])
corners = np.int32( cv2.perspectiveTransform(corners.reshape(1, -1, 2), H).reshape(-1, 2) + (w1, 0) )
cv2.polylines(vis, [corners], True, (0, 0, 255))
cv2.imshow(win, vis)
return vis
if __name__ == '__main__':
img1 = cv2.imread('rB4Yy_big.jpg' , 0)
img2 = cv2.imread('ZjBAA.jpg', 0)
detector, matcher = init_feature()
kp1, desc1 = detector.detectAndCompute(img1, None)
kp2, desc2 = detector.detectAndCompute(img2, None)
raw_matches = matcher.knnMatch(desc1, trainDescriptors = desc2, k = 2)
p1, p2, kp_pairs = filter_matches(kp1, kp2, raw_matches)
if len(p1) >= 4:
H, status = cv2.findHomography(p1, p2, cv2.RANSAC, 5.0)
print('%d / %d inliers/matched' % (np.sum(status), len(status)))
vis = explore_match('find_obj', img1, img2, kp_pairs, status, H)
cv2.waitKey()
cv2.destroyAllWindows()
else:
print('%d matches found, not enough for homography estimation' % len(p1))
#/usr/bin/env python
#Python 2/3兼容性
来自未来导入打印功能
将numpy作为np导入
进口cv2
def初始功能()
检测器=cv2.BRISK_create()
norm=cv2.norm\u HAMMING
匹配器=cv2.bMatcher(标准)
回波检测器
def过滤器匹配(kp1、kp2、匹配,比率=0.75):
mkp1,mkp2=[],[]
对于匹配中的m:
如果len(m)==2且m[0]。距离=4:
H、 状态=cv2.findHomography(p1,p2,cv2.RANSAC,5.0)
打印(“%d/%d个内联项/匹配的“%”(np.sum(状态),len(状态)))
vis=探索匹配(“查找对象”,img1,img2,kp对,状态,H)
cv2.waitKey()
cv2.destroyAllWindows()
其他:
打印(“%d个匹配项已找到,不足以进行单应估计“%len(p1))
您可以使用模板匹配,即带有描述符的关键点,而不是模板匹配。它们是缩放不变的,因此您不需要迭代不同的缩放版本