Tôi đang cố gắng sử dụng OpenCV để phân đoạn một thanh cong từ nền của nó rồi tìm các đường cong trong đó và tính toán góc giữa mỗi khúc cua.Làm thế nào để phân đoạn thanh cong để tính toán góc?
Phần đầu tiên may mắn là tầm thường với độ tương phản đủ giữa nền trước và nền sau. Một chút xói mòn/giãn nở sẽ chăm sóc phản xạ/điểm nổi bật khi phân đoạn.
Phần thứ hai là nơi tôi không chắc chắn cách tiếp cận.
Tôi có thể dễ dàng lấy đường bao (trên cùng và dưới cùng rất giống nhau, hoặc sẽ làm), nhưng tôi không thể tìm ra cách tách đường bao thành các phần thẳng và thanh uốn để tính Các góc.
Cho đến nay tôi đã thử đơn giản hóa các đường nét, nhưng tôi nhận được quá nhiều hoặc quá ít điểm và cảm thấy khó khăn khi chỉ định đúng cài đặt để giữ các bộ phận thẳng thẳng và phần cong đơn giản.
Dưới đây là hình ảnh đầu vào của tôi (bend.png)
Và đây là những gì tôi đã cố gắng cho đến nay:
#!/usr/bin/env python
import numpy as np
import cv2
threshold = 229
# erosion/dilation kernel
kernel = np.ones((5,5),np.uint8)
# contour simplification
epsilon = 0
# slider callbacks
def onThreshold(x):
global threshold
print "threshold = ",x
threshold = x
def onEpsilon(x):
global epsilon
epsilon = x * 0.01
print "epsilon = ",epsilon
# make a window to add sliders/preview to
cv2.namedWindow('processed')
#make some sliders
cv2.createTrackbar('threshold','processed',60,255,onThreshold)
cv2.createTrackbar('epsilon','processed',1,1000,onEpsilon)
# load image
img = cv2.imread('bend.png',0)
# continuously process for quick feedback
while 1:
# exit on ESC key
k = cv2.waitKey(1) & 0xFF
if k == 27:
break
# Threshold
ret,processed = cv2.threshold(img,threshold,255,0)
# Invert
processed = (255-processed)
# Dilate
processed = cv2.dilate(processed,kernel)
processed = cv2.erode(processed,kernel)
# Canny
processed = cv2.Canny(processed,100,200)
contours, hierarchy = cv2.findContours(processed,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
if len(contours) > 0:
approx = cv2.approxPolyDP(contours[0],epsilon,True)
# print len(approx)
cv2.drawContours(processed, [approx], -1, (255,255,255), 3)
demo = img.copy()
cv2.drawContours(demo, [approx], -1, (192,0,0), 3)
# show result
cv2.imshow('processed ',processed)
cv2.imshow('demo ',demo)
# exit
cv2.destroyAllWindows()
Đây là những gì tôi đã có cho đến nay, nhưng Tôi không tin rằng đây là phương pháp tốt nhất:
Tôi đã cố gắng để con số này ra thị và những gì tôi đã nhắm vào là một cái gì đó dọc theo những dòng:
Bởi vì mục tiêu cuối cùng là để tính toán góc giữa các bộ phận cong một cái gì đó như thế này cảm thấy đơn giản hơn:
giả định của tôi mà lắp đường dây và tính góc giữa cặp int dòng ersecting có thể làm việc:
tôi đã làm một thử nghiệm nhanh bằng cách sử dụng HoughLines OpenCV Python tutorial, nhưng không phụ thuộc vào các thông số thông qua tôi đã không nhận được kết quả tuyệt vời:
#!/usr/bin/env python
import numpy as np
import cv2
threshold = 229
minLineLength = 30
maxLineGap = 10
houghThresh = 15
# erosion/dilation kernel
kernel = np.ones((5,5),np.uint8)
# slider callbacks
def onMinLineLength(x):
global minLineLength
minLineLength = x
print "minLineLength = ",x
def onMaxLineGap(x):
global maxLineGap
maxLineGap = x
print "maxLineGap = ",x
def onHoughThresh(x):
global houghThresh
houghThresh = x
print "houghThresh = ",x
# make a window to add sliders/preview to
cv2.namedWindow('processed')
#make some sliders
cv2.createTrackbar('minLineLength','processed',1,50,onMinLineLength)
cv2.createTrackbar('maxLineGap','processed',5,30,onMaxLineGap)
cv2.createTrackbar('houghThresh','processed',15,50,onHoughThresh)
# load image
img = cv2.imread('bend.png',0)
# continuously process for quick feedback
while 1:
# exit on ESC key
k = cv2.waitKey(1) & 0xFF
if k == 27:
break
# Threshold
ret,processed = cv2.threshold(img,threshold,255,0)
# Invert
processed = (255-processed)
# Dilate
processed = cv2.dilate(processed,kernel)
processed = cv2.erode(processed,kernel)
# Canny
processed = cv2.Canny(processed,100,200)
lineBottom = np.zeros(img.shape,np.uint8)
contours, hierarchy = cv2.findContours(processed,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
if len(contours) > 0:
cv2.drawContours(lineBottom, contours, 0, (255,255,255), 1)
# HoughLinesP
houghResult = img.copy()
lines = cv2.HoughLinesP(lineBottom,1,np.pi/180,houghThresh,minLineLength,maxLineGap)
try:
for x in range(0, len(lines)):
for x1,y1,x2,y2 in lines[x]:
cv2.line(houghResult,(x1,y1),(x2,y2),(0,255,0),2)
except Exception as e:
print e
# show result
cv2.imshow('lineBottom',lineBottom)
cv2.imshow('houghResult ',houghResult)
# exit
cv2.destroyAllWindows()
Is đây là một cách tiếp cận khả thi? Nếu vậy, cách chính xác để làm phù hợp với dòng trong Python OpenCV là gì?
Nếu không, đó là cách tốt nhất để giải quyết vấn đề này?
Cập nhật Tiếp theo lời khuyên của Miki Tôi đã thử LSD OpenCV 3 và có kết quả đẹp hơn với HoughLinesP
nhưng có vẻ như vẫn còn một số điều chỉnh cần thiết, mặc dù nó không giống khác hơn cv2.createLineSegmentDetector
không có nhiều lựa chọn để chơi với:
Tôi đã làm một cái gì đó rất giống với approxPolyDP, cuối cùng sáp nhập gần như collinear phân đoạn tiếp theo/đoạn ngắn. – Miki
Một cách tiếp cận khác là sử dụng LSD (máy phát hiện phân đoạn đường) ... Tôi chưa bao giờ sử dụng nó, nhưng đáng để thử – Miki
@Miki nghe có vẻ thú vị. Tôi bắt đầu với approxPolyDP, nhưng không biết phải làm gì với nó tiếp theo. Vì vậy, bạn về cơ bản looped thông qua các dòng và nếu sự khác biệt góc giữa các cặp đường dưới một ngưỡng bạn sáp nhập chúng thành một dòng, phải không? –