У меня есть несколько отсканированных изображений, которые я хотел бы вычислить с помощью Python / Opencv. Каждое из этих изображений (см. Пример ниже) содержит n строк цветных квадратов. Каждый из этих квадратов имеет одинаковый размер. Цель состоит в том, чтобы обрезать каждый из этих квадратов и извлечь из него данные.
Я нашел там код, который может извлекать квадраты из изображения.
Вот мой код, в котором я его использовал:
import numpy as np
import cv2
from matplotlib import pyplot as plt
def angle_cos(p0, p1, p2):
import numpy as np
d1, d2 = (p0-p1).astype('float'), (p2-p1).astype('float')
return abs( np.dot(d1, d2) / np.sqrt( np.dot(d1, d1)*np.dot(d2, d2) ) )
def find_squares(img):
import cv2 as cv
import numpy as np
img = cv.GaussianBlur(img, (5, 5), 0)
squares = []
for gray in cv.split(img):
for thrs in range(0, 255, 26):
if thrs == 0:
bin = cv.Canny(gray, 0, 50, apertureSize=5)
bin = cv.dilate(bin, None)
else:
_retval, bin = cv.threshold(gray, thrs, 255, cv.THRESH_BINARY)
contours, _hierarchy = cv.findContours(bin, cv.RETR_LIST, cv.CHAIN_APPROX_SIMPLE)
for cnt in contours:
cnt_len = cv.arcLength(cnt, True)
cnt = cv.approxPolyDP(cnt, 0.02*cnt_len, True)
if len(cnt) == 4 and cv.contourArea(cnt) > 1000 and cv.isContourConvex(cnt):
cnt = cnt.reshape(-1, 2)
max_cos = np.max([angle_cos( cnt[i], cnt[(i+1) % 4], cnt[(i+2) % 4] ) for i in range(4)])
if max_cos < 0.1:
squares.append(cnt)
print(len(squares))
return squares
img = cv2.imread("test_squares.jpg",1)
plt.axis("off")
plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
plt.show()
squares = find_squares(img)
cv2.drawContours( img, squares, -1, (0, 255, 0), 1 )
plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
plt.show()
Однако он находит два много квадратов (100 вместо 15 !!). Глядя на изображение, кажется, что Opencv находит много контуров для каждого квадрата.
Я почти уверен, что его можно оптимизировать, поскольку квадраты более или менее одинакового размера и находятся далеко друг от друга. Будучи новичком в Opencv, я еще не нашел способа дать больше критериев в функции «найти квадраты», чтобы получить только 15 квадратов в конце процедуры. Может быть, площадь контура можно увеличить?
Я также нашел там более подробный код (очень близкий к предыдущему), но, похоже, он был разработан в старой версии Opencv. Мне не удалось заставить его работать (и, следовательно, изменить его).