无法检测图像上的等号
can't detect equal sign on image
我正在从事一个理解数学符号的计算机视觉项目。除了“等于”标记外,它都能正确检测到所有内容。但是“等号”被视为两个独立的“减号”。
image = cv2.imread('./deneme.png')
grey = cv2.cvtColor(image.copy(), cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(grey.copy(), 0, 255, cv2.THRESH_BINARY_INV)
contours, _ = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
preprocessed_digits = []
for c in contours:
x,y,w,h = cv2.boundingRect(c)
cv2.rectangle(image, (x,y), (x+w, y+h), color=(0, 255, 0), thickness=2)
digit = thresh[y:y+h, x:x+w]
digit = make_square(digit)
preprocessed_digits.append(digit)
plt.imshow(image, cmap="gray")
plt.show()
我不知道如何解决这个问题。如何检测等号?
这是您想要达到的结果吗?
由于您的数学表达式似乎是水平书写的,正如@Micka 指出的那样,您对等号的两个不同分量之间的关系有很强的先验,所以有 straight-forward(但是 hacky) 检测减号何时实际上是相等的方法:
import cv2
import matplotlib.pyplot as plt
import numpy as np
class Rect:
def __init__(self,
a,
b,
c,
d):
self.a=a
self.b=b
self.c=c
self.d=d
self.center=np.array([(a+c)/2, (b+d)/2])
def merge_rectangles(r_1, r_2):
a_m= min(r_1.a, r_2.a)
b_m= min(r_1.b, r_2.b)
c_M= max(r_1.c, r_2.c)
d_M= max(r_1.d, r_2.d)
return Rect(a_m, b_m, c_M, d_M)
def they_form_an_equal_sign(rect_1,
rect_2,
tol_w=10,#in pixels
tol_h=10):
#check if the bounding boxes approximately align
b0 = (np.abs(rect_1.a - rect_2.a) < tol_w ) and (np.abs(rect_1.c - rect_2.c) < tol_w)
#check if the bounding boxes have approximately the same height
h1 = np.abs(rect_1.d - rect_1.b)
h2 = np.abs(rect_2.d - rect_2.b)
b1 = np.abs(h1-h2) < tol_h
return b0 and b1
image = cv2.imread('/tmp/m.png')
grey = cv2.cvtColor(image.copy(), cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(grey.copy(), 0, 255, cv2.THRESH_BINARY_INV)
contours, _ = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
candidate_rectangles=[]
for c in contours:
x,y,w,h = cv2.boundingRect(c)
candidate_rectangles.append(Rect(x,y,x+w,y+h))
kept=np.ones(len(candidate_rectangles))
new_rectangles=[]
for i in range(len(candidate_rectangles)):
for j in range(i+1,len(candidate_rectangles)):
b=they_form_an_equal_sign(candidate_rectangles[i], candidate_rectangles[j])
if b:
new_rect=merge_rectangles(candidate_rectangles[i], candidate_rectangles[j])
new_rectangles.append(new_rect)
kept[i]=0
kept[j]=0
for i in range(len(kept)):
if kept[i]:
rect=candidate_rectangles[i]
cv2.rectangle(image, (rect.a, rect.b), (rect.c, rect.d), color=(0, 255, 0), thickness=2)
for rect in new_rectangles:
cv2.rectangle(image, (rect.a, rect.b), (rect.c, rect.d), color=(0, 255, 0), thickness=2)
plt.imshow(image, cmap="gray")
plt.show()
基本上,这采用 brute-force 方法来比较代码中检测到的每两个边界框,如果它们满足您之前的要求,则将它们合并为一个更大的边界框:即 如果它们是水平排列的(就像减号的顶部和底部应该的那样)并且它们的高度大致相同。
但是,这显然不够稳健:您需要调整阈值,如果您的表达式不是水平的并且没有明显分开,那么整个事情就会分崩离析。如果您想要一个更 robust/useful 的系统,用于字符识别的基本 ML 方法是一个更好的起点。
我正在从事一个理解数学符号的计算机视觉项目。除了“等于”标记外,它都能正确检测到所有内容。但是“等号”被视为两个独立的“减号”。
image = cv2.imread('./deneme.png')
grey = cv2.cvtColor(image.copy(), cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(grey.copy(), 0, 255, cv2.THRESH_BINARY_INV)
contours, _ = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
preprocessed_digits = []
for c in contours:
x,y,w,h = cv2.boundingRect(c)
cv2.rectangle(image, (x,y), (x+w, y+h), color=(0, 255, 0), thickness=2)
digit = thresh[y:y+h, x:x+w]
digit = make_square(digit)
preprocessed_digits.append(digit)
plt.imshow(image, cmap="gray")
plt.show()
我不知道如何解决这个问题。如何检测等号?
这是您想要达到的结果吗?
由于您的数学表达式似乎是水平书写的,正如@Micka 指出的那样,您对等号的两个不同分量之间的关系有很强的先验,所以有 straight-forward(但是 hacky) 检测减号何时实际上是相等的方法:
import cv2
import matplotlib.pyplot as plt
import numpy as np
class Rect:
def __init__(self,
a,
b,
c,
d):
self.a=a
self.b=b
self.c=c
self.d=d
self.center=np.array([(a+c)/2, (b+d)/2])
def merge_rectangles(r_1, r_2):
a_m= min(r_1.a, r_2.a)
b_m= min(r_1.b, r_2.b)
c_M= max(r_1.c, r_2.c)
d_M= max(r_1.d, r_2.d)
return Rect(a_m, b_m, c_M, d_M)
def they_form_an_equal_sign(rect_1,
rect_2,
tol_w=10,#in pixels
tol_h=10):
#check if the bounding boxes approximately align
b0 = (np.abs(rect_1.a - rect_2.a) < tol_w ) and (np.abs(rect_1.c - rect_2.c) < tol_w)
#check if the bounding boxes have approximately the same height
h1 = np.abs(rect_1.d - rect_1.b)
h2 = np.abs(rect_2.d - rect_2.b)
b1 = np.abs(h1-h2) < tol_h
return b0 and b1
image = cv2.imread('/tmp/m.png')
grey = cv2.cvtColor(image.copy(), cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(grey.copy(), 0, 255, cv2.THRESH_BINARY_INV)
contours, _ = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
candidate_rectangles=[]
for c in contours:
x,y,w,h = cv2.boundingRect(c)
candidate_rectangles.append(Rect(x,y,x+w,y+h))
kept=np.ones(len(candidate_rectangles))
new_rectangles=[]
for i in range(len(candidate_rectangles)):
for j in range(i+1,len(candidate_rectangles)):
b=they_form_an_equal_sign(candidate_rectangles[i], candidate_rectangles[j])
if b:
new_rect=merge_rectangles(candidate_rectangles[i], candidate_rectangles[j])
new_rectangles.append(new_rect)
kept[i]=0
kept[j]=0
for i in range(len(kept)):
if kept[i]:
rect=candidate_rectangles[i]
cv2.rectangle(image, (rect.a, rect.b), (rect.c, rect.d), color=(0, 255, 0), thickness=2)
for rect in new_rectangles:
cv2.rectangle(image, (rect.a, rect.b), (rect.c, rect.d), color=(0, 255, 0), thickness=2)
plt.imshow(image, cmap="gray")
plt.show()
基本上,这采用 brute-force 方法来比较代码中检测到的每两个边界框,如果它们满足您之前的要求,则将它们合并为一个更大的边界框:即 如果它们是水平排列的(就像减号的顶部和底部应该的那样)并且它们的高度大致相同。
但是,这显然不够稳健:您需要调整阈值,如果您的表达式不是水平的并且没有明显分开,那么整个事情就会分崩离析。如果您想要一个更 robust/useful 的系统,用于字符识别的基本 ML 方法是一个更好的起点。