OpenCV / C ++ kết nối các đường viền gần đó dựa trên khoảng cách giữa chúng


15

Tôi phải kết nối các đường viền gần đó trong một hình ảnh dựa trên khoảng cách giữa chúng để xác định xem các đường viền có được kết nối hay không.

Bây giờ đã có một câu hỏi về cùng một vấn đề ở đây /programming/8973017/opencv-c-obj-c-connect-gầnby-contours nhưng ở đây anh ta hợp nhất tất cả các đường viền thành một. Điều này tôi không muốn. Tôi không nghĩ rằng có một số chức năng trong opencv cho điều này nhưng bạn có thể đề xuất một thuật toán cho điều đó. Ứng dụng của tôi đi như thế này:

Tôi đang phát hiện bàn tay, vì vậy tôi đã sử dụng thuật toán phát hiện da để xác định chúng nhưng vì da tôi không trắng và có thể do điều kiện làm sáng đôi khi đường viền bị vỡ ở khuỷu tay. Vì vậy, tôi muốn các đường viền gần đó được kết nối nhưng không phải tất cả chúng (bởi vì cả hai tay của tôi sẽ ở đó theo đường viền.) (Bằng tay tôi có nghĩa là từ vai đến lòng bàn tay.)

Ngoài ra, tôi nghĩ rằng bằng cách sử dụng một số phát hiện cạnh, tôi sẽ có được ranh giới tay và phát hiện nếu một số bản vá bên trong ranh giới này được phát hiện là da thì toàn bộ khu vực trong ranh giới này sẽ được phát hiện là da nhưng tôi không chắc làm thế nào để làm điều này phần.

Bất kỳ trợ giúp sẽ được đánh giá cao. Cảm ơn trước

Hình ảnh mẫu:

nhập mô tả hình ảnh ở đây

Trong hình ảnh này, tôi muốn kết nối các điểm (8 kết nối) có khoảng cách dưới 40 pixel để tôi có được bàn tay trái của mình dưới dạng một đường viền

Mục đích của tôi là chỉ lấy đường viền tay (tôi không quan tâm đến bất kỳ khu vực nào khác)


bằng tay bạn thực sự có nghĩa là cánh tay. bạn có thể không chỉ điều chỉnh màu sắc bạn sử dụng để phát hiện da phù hợp với màu da của bạn?
ispinator

Tôi đã làm điều đó và nó cho đầu ra tốt (Khi da tôi được chiếu sáng). Vì vậy, trong buổi tối nó đến như được hiển thị. Dù sao, tôi nghĩ rằng có thể có một số phương pháp để kết nối các đốm màu gần đó.
Đảo Roney


Chào mừng đến với trao đổi ngăn xếp. SE không phải là một diễn đàn! Đây không phải là một câu trả lời cho câu hỏi. Nếu bạn có một câu hỏi về câu hỏi - hãy đặt câu hỏi này làm nhận xét.
Dipan Mehta

Làm thế nào để bạn phát hiện ra da?
nkint

Câu trả lời:


10

Nếu bạn không lo lắng về tốc độ hoặc đường viền chính xác của bàn tay, dưới đây là một giải pháp đơn giản.

Phương pháp như sau: Bạn lấy từng đường viền và tìm khoảng cách đến các đường viền khác. Nếu khoảng cách nhỏ hơn 50, chúng ở gần và bạn đặt chúng lại với nhau. Nếu không, chúng được đặt như khác nhau.

Vì vậy, kiểm tra khoảng cách đến từng đường viền là một quá trình tốn thời gian. Mất vài giây. Vì vậy, không có cách nào bạn có thể làm điều đó thời gian thực.

Ngoài ra, để tham gia các đường viền, tôi đặt chúng vào một bộ duy nhất và vẽ một thân tàu lồi cho bộ đó. Vì vậy, kết quả bạn nhận được thực sự là một tay lồi, không phải tay thật.

Dưới đây là đoạn mã của tôi trong OpenCV-Python. Tôi chưa đi để tối ưu hóa, chỉ muốn nó hoạt động, thế thôi. Nếu nó giải quyết vấn đề của bạn, hãy tối ưu hóa.

import cv2
import numpy as np

def find_if_close(cnt1,cnt2):
    row1,row2 = cnt1.shape[0],cnt2.shape[0]
    for i in xrange(row1):
        for j in xrange(row2):
            dist = np.linalg.norm(cnt1[i]-cnt2[j])
            if abs(dist) < 50 :
                return True
            elif i==row1-1 and j==row2-1:
                return False

img = cv2.imread('dspcnt.jpg')
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
ret,thresh = cv2.threshold(gray,127,255,0)
contours,hier = cv2.findContours(thresh,cv2.RETR_EXTERNAL,2)

LENGTH = len(contours)
status = np.zeros((LENGTH,1))

for i,cnt1 in enumerate(contours):
    x = i    
    if i != LENGTH-1:
        for j,cnt2 in enumerate(contours[i+1:]):
            x = x+1
            dist = find_if_close(cnt1,cnt2)
            if dist == True:
                val = min(status[i],status[x])
                status[x] = status[i] = val
            else:
                if status[x]==status[i]:
                    status[x] = i+1

unified = []
maximum = int(status.max())+1
for i in xrange(maximum):
    pos = np.where(status==i)[0]
    if pos.size != 0:
        cont = np.vstack(contours[i] for i in pos)
        hull = cv2.convexHull(cont)
        unified.append(hull)

cv2.drawContours(img,unified,-1,(0,255,0),2)
cv2.drawContours(thresh,unified,-1,255,-1)

Dưới đây là kết quả tôi nhận được:

nhập mô tả hình ảnh ở đây

nhập mô tả hình ảnh ở đây


Làm thế nào điều này có thể được thực hiện trong c ++? Tôi có phần findContour nhưng sau đó tôi dường như không thể lấy các đường viền để bọc trong một đa giác như hình trên (trái ngược với hình chữ nhật giới hạn).
Elionardo Feliciano

Tôi đánh giá cao cách tiếp cận của bạn và đã cố gắng áp dụng cho trường hợp của tôi nhưng thật không may, nó cực kỳ chậm trên Python (mặc dù máy tính xách tay của tôi có Core i7QM và RAM 8GB). Tôi sử dụng MSER để phát hiện các vùng và bây giờ cần xác định cặp vùng nào "liền kề", tôi đã thử thuật toán của bạn với ngưỡng 10 ... Phải mất nhiều năm để trả về các vùng liền kề.
Jim Raynor

4

Để khắc phục sự cố kết nối, bạn có thể thử thao tác chặt chẽ:

cv::Mat structuringElement = cv::getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(40, 40));
cv::morphologyEx( inputImage, outputImage, cv::MORPH_CLOSE, structuringElement );

Tôi nghi ngờ rằng điều này sẽ tạo ra kết quả mà bạn muốn, nhưng bạn có thể thử nó.


2

Có vẻ như bạn đang "giám sát" hình ảnh của mình. Hoạt động hình thái, như bjnoernz đã đề xuất, sẽ giúp đỡ. Cụ thể, một cách tiếp cận đầu nguồn sẽ tiến gần hơn đến những gì bạn muốn thay vì chỉ kiểm tra khoảng cách (như trong ví dụ về python ở trên). Xem http://cmm.ensmp.fr/~beucher/wtshed.html .

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.