Найти центральную линию между краями объекта - PullRequest
0 голосов
/ 17 октября 2018

enter image description here

Сегодня я пытаюсь определить край объекта.

Я получил отличный результат, сделав это.

import cv2
img = cv2.imread("0.png")
img2 = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
img2 = cv2.equalizeHist(img2)
img2 = cv2.GaussianBlur(img2, (7, 7), 0)
edges = cv2.Canny(img2, 180, 300)
im2, contours, hierarchy = cv2.findContours(edges, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
cv2.drawContours(img, contours, -1, (0, 255, 0), 1)
cv2.imshow('img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

и изображение выглядит следующим образом: (это сварочный рентген) image with edges

Моя конечная цель - найти центральную линию между краями (коллекция(MaxY + MinY) / 2 на каждом X) идеальный результат должен выглядеть следующим образом: (извините за плохой рисунок руки)

image with center line

Может ли кто-нибудьдайте мне знать, как мне это сделать?Большое спасибо.

1 Ответ

0 голосов
/ 17 октября 2018

Прежде всего вы должны подготовить свое изображение так, чтобы вы могли найти свой единственный контур (порог, выравнивание гистограммы и т. Д.).Контур возвращает вам набор (x, y) координат, которые представляют контур, поэтому для первого шага вы должны отделить верхний край от нижнего (разделить его на половину).В моем примере я сделал его дополняющим моменты контура, но учтите, что это не сработает для изогнутых линий!Вам нужно будет сделать алгоритм для разделения верхней и нижней сторон.Сделав это, вы можете составить два списка, содержащих один элемент на координату x.Затем просто вычислите середину и наведите точку на изображение.

Пример кода:

import cv2
import numpy as np

img = cv2.imread('centerline.png')
mask = np.zeros((img.shape[:2]), np.uint8)
h2, w2 = img.shape[:2]

gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
equ = cv2.equalizeHist(gray)

_, thresh = cv2.threshold(equ,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
kernel = np.ones((5,5),np.uint8)
opening = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel)

_, contours, hierarchy = cv2.findContours(opening,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
for cnt in contours:
    x,y,w,h = cv2.boundingRect(cnt)
    print(h, w)
    if h < 30 and w > 270:
        cv2.drawContours(mask, [cnt], 0, (255,255,255), -1)

res = cv2.bitwise_and(img, img, mask=mask)
gray = cv2.cvtColor(res,cv2.COLOR_BGR2GRAY)
_, thresh = cv2.threshold(gray,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
blur = cv2.GaussianBlur(thresh,(5,5),0)
_, contours, hierarchy = cv2.findContours(blur,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
cnt = max(contours, key=cv2.contourArea)

M = cv2.moments(cnt)
cy = int(M['m01']/M['m00'])

mask = np.zeros((img.shape[:2]), np.uint8)
cv2.drawContours(mask, [cnt], 0, (255,255,255), -1)

up = []
down = []

for i in cnt:
    x = i[0][0]
    y = i[0][1]
    if x == 0:
        pass
    elif x == w2:
        pass
    else:
        if y > cy:
            down.append(tuple([x,y]))
        elif y < cy:
            up.append(tuple([x,y]))
        else:
            pass


up.sort(key = lambda x: x[0])
down.sort(key = lambda x: x[0])

up_1 = []
down_1 = []

for i in range(0, len(up)-1):
    if up[i][0] != up[i+1][0]:
        up_1.append(up[i])
    else:
        pass

for i in range(0, len(down)-1):
    if down[i][0] != down[i+1][0]:
        down_1.append(down[i])
    else:
        pass

lines = zip(up_1, down_1)

for i in lines:
    x1 = i[0][0]
    y1 = i[0][1]
    x2 = i[1][0]
    y2 = i[1][1]
    middle = np.sqrt(((x2-x1)**2)+((y2-y1)**2))
    cv2.circle(img, (x1, y1+int(middle/2)), 1, (0,0,255), -1)    

cv2.imshow('img', img)

Результат:

enter image description here

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