Удалить контуры OpenCV - PullRequest
0 голосов
/ 19 июня 2020

Мое изображение

Я хочу получить

https://ibb.co/t8hNkM2

Я мог только получить

Мне удалось найти максимальный контур

def img_counter_max(image_file: str):
    img = cv2.imread(image_file)
    # grayscale
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)  # меняем цветовую модель с BGR на HSV
    cv2.waitKey(0)
    # binarize
    ret, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY_INV)
    cv2.waitKey(0)
    # find contours
    ctrs, hier = cv2.findContours(thresh.copy(), cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
    # sort contours
    sorted_ctrs = sorted(ctrs, key=lambda ctr: cv2.boundingRect(ctr)[0])
    # sorted_ctrs sorted(ctrs, key=cv2.contourArea, reverse=True)[0]
    contour_sizes = [(cv2.contourArea(contour), contour) for contour in sorted_ctrs]
    biggest_contour = max(contour_sizes, key=lambda x: x[0])[1]
    x, y, w, h = cv2.boundingRect(biggest_contour)
    roi = img[y:y + h, x:x + w]
    cv2.imwrite("C:\\Users\\dennn\\PycharmProjects\\untitled2\\imag\\roi1.jpg", 
    roi)
    cv2.rectangle(img, (x, y), (x + w, y + h), (90, 255, 0), 2)
    from tensorflow.python import Size
    resize_img = cv2.resize(img, (512,512))
    # cv2.resize(img, Size(512,512), interpolation=cv2.INTER_AREA)
    cv2.namedWindow("Display frame", cv2.WINDOW_AUTOSIZE);
    cv2.imshow('Display frame', resize_img)
    cv2.waitKey(0)

Как получить нужное мне изображение?

Ответы [ 2 ]

1 голос
/ 19 июня 2020

Я обнаружил, что сортировка по contourArea() дает неверные результаты. Вероятно, он вычисляет все точки внутри контура, но не область прямоугольника, которую он использует - и этот прямоугольник может быть больше.

Я использую boundingRect(), чтобы получить прямоугольник, используемый контуром, и позже вычислить размер, используя w*h, а затем он правильно сортирует контуры.

Я использую for -l oop чтобы отобразить изображение с разными прямоугольниками и посмотреть, какой контур дает ожидаемую область. Таким образом, я вижу, что третий контур дает ожидаемую область, поэтому я могу использовать [2], чтобы получить и сохранить.


В конечном итоге я бы использовал размер для выбора области, в которой w*h находится в некотором диапазоне

expecte_region_size - range < w*h < expecte_region_size + range

В конце концов я бы использовал for -l oop которые отображают изображение с различными прямоугольниками, чтобы вручную выбрать прямоугольник для сохранения в файл.


import cv2

img = cv2.imread('image.jpg')

# grayscale
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)  # меняем цветовую модель с BGR на HSV

# binarize
ret, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY_INV)

# find contours
ctrs, hier = cv2.findContours(thresh.copy(), cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)

# find rect and area - and create items [contour, rect, area] - but sorting by area gives wrong results
#items = [[ctr, cv2.boundingRect(ctr), cv2.contourArea(ctr)] for ctr in ctrs]

# find rect - and create items [contour, rect]
items = [[ctr, cv2.boundingRect(ctr)] for ctr in ctrs]

# find rect's size and create items [contour, rect, size]
items = [[ctr, rect, rect[2]*rect[3]] for ctr, rect in items]

# sort by size 
items = sorted(items, key=lambda x: x[2], reverse=True)

for index, item in enumerate(items[:5]):

    contour = item[0]
    x, y, w, h = item[1]
    size = item[2]

    print(index, '->', size, '(', x, y, w, h, ')')

    img_copy = img.copy()
    cv2.rectangle(img_copy, (x, y), (x + w, y + h), (0, 0, 255), 15)
    resize_img = cv2.resize(img_copy, (512,512))

    cv2.imshow('frame', resize_img)
    cv2.waitKey(0)

cv2.destroyAllWindows()

# --- save image ---

item = items[2]

contour = item[0]
x, y, w, h = item[1]
size = item[2]

img = img[y:y+h, x:x+w]
cv2.imwrite('output.jpg', img)

Предварительный просмотр:

enter image description here

Выход:

enter image description here

0 голосов
/ 20 июня 2020

Код хорошо находит символы, но выводит их не по порядку Я нашел фрагмент кода, который должен решить эту проблему, но не могу - после нахождения контуров с помощью contours = cv2.findContours () используйте -

   boundary=[]
   for c,cnt in enumerate(contours):
   x,y,w,h = cv2.boundingRect(cnt)
   boundary.append((x,y,w,h))
   count=np.asarray(boundary)
   max_width = np.sum(count[::, (0, 2)], axis=1).max()
   max_height = np.max(count[::, 3])
   nearest = max_height * 1.4
   ind_list=np.lexsort((count[:,0],count[:,1]))

   c=count[ind_list]

Найти символы

 img = "C:\\Users\\dennn\\PycharmProjects\\untitled2\\output.jpg"      dir = os.curdir

 path = os.path.join(dir,img)
 raw_image = cv2.imread(path,0)

 cv2.imshow("original",raw_image)
 plt.subplot(2,3,1)
 plt.title("Original")
 plt.imshow(raw_image,'gray')
 plt.xticks([]),plt.yticks([]);

 sm_image = cv2.blur(raw_image,(8,8))

 cv2.imshow("smoothed",sm_image)

 plt.subplot(2,3,2)
 plt.title("Smoothed")
 plt.imshow(sm_image,'gray')
 plt.xticks([]),plt.yticks([]);

 #cv2.imshow("smoothed",sm_image)
 ret,bw_image = cv2.threshold(sm_image,160,255,cv2.THRESH_BINARY_INV)

 cv2.imshow("thresholded",bw_image)
 plt.subplot(2,3,3)
 plt.title("Thresholded")
 plt.imshow(bw_image,'gray')
 plt.xticks([]),plt.yticks([]);

 kernel = np.ones((4,4),np.uint8)
 er_image = cv2.erode(bw_image,kernel)

 cv2.imshow("eroded",er_image)
 plt.subplot(2,3,4)
 plt.title("Eroded")
 plt.imshow(er_image,'gray')
 plt.xticks([]),plt.yticks([]);

 kernel = np.ones((2,2),np.uint8)
 di_image = cv2.dilate(er_image,kernel)

 cv2.imshow("dilated",di_image)
 plt.title("Dilated")
 plt.subplot(2,3,5)
 plt.imshow(di_image,'gray')
 plt.xticks([]),plt.yticks([]);

 mo_image = di_image.copy()
 contour0 = 
 cv2.findContours(mo_image.copy(),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
 contours = [cv2.approxPolyDP(cnt,3,True) for cnt in contour0[0]]

 maxArea = 0
 rect = []
 for ctr in contours:
  maxArea = max(maxArea, cv2.contourArea(ctr))

 if img == "C:\\Users\\dennn\\PycharmProjects\\untitled2\\output.jpg":
 areaRatio = 0.05

 for ctr in contours:
     if cv2.contourArea(ctr) > maxArea * areaRatio:
      rect.append(cv2.boundingRect(cv2.approxPolyDP(ctr, 1, True)))

symbols = []
for i in rect:
x = i[0]
y = i[1]
w = i[2]
h = i[3]
p1 = (x, y)
p2 = (x + w, y + h)
cv2.rectangle(mo_image, p1, p2, 255, 2)
image = cv2.resize(mo_image[y:y + h, x:x + w], (32, 32))
symbols.append(image.reshape(1024, ).astype("uint8"))

testset_data = np.array(symbols)

cv2.imshow("segmented", mo_image)
plt.subplot(2, 3, 6)
plt.title("Segmented")
plt.imshow(mo_image, 'gray')
plt.xticks([]), plt.yticks([]);
# plt.show()

# garbage collection
cv2.destroyAllWindows()
plt.close()

# show glyphs
for i in range(len(symbols)):
image = np.zeros(shape=(64,64))
image[15:47,15:47] = symbols[i].reshape((32,32))
cv2.imshow("sym",image)
cv2.waitKey(0)

cv2.destroyAllWindows()
plt.close()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...