OpenCV / C ++ menghubungkan kontur terdekat berdasarkan jarak di antara mereka

15

Saya harus menghubungkan kontur terdekat dalam gambar berdasarkan jarak di antara mereka yang menentukan apakah kontur harus dihubungkan.

Sekarang sudah ada pertanyaan tentang masalah yang sama di sini /programming/8973017/opencv-c-obj-c-connect-nearby-contours tetapi di sini ia menggabungkan semua kontur menjadi satu. Saya tidak mau ini. Saya tidak berpikir bahwa ada beberapa fungsi dalam OpenCV untuk ini tetapi Anda dapat menyarankan algoritma untuk itu. Aplikasi saya berjalan seperti ini:

Saya mendeteksi tangan, jadi saya menggunakan algoritma pendeteksian kulit untuk menentukannya, tetapi karena kulit saya tidak putih dan mungkin karena kondisi keringanan kadang-kadang kontur patah pada siku. Jadi saya ingin kontur terdekat terhubung tetapi tidak semuanya (karena kedua tangan saya akan ada di kontur.) (Dengan tangan saya maksudkan dari bahu ke telapak tangan.)

Selain itu saya berpikir bahwa dengan menggunakan beberapa deteksi tepi saya akan mendapatkan batas tangan saya dan mendeteksi jika beberapa patch di dalam batas ini terdeteksi sebagai kulit maka seluruh wilayah dalam batas ini akan terdeteksi sebagai kulit tetapi saya tidak yakin bagaimana melakukan ini. bagian.

Bantuan apa pun akan dihargai. Terima kasih sebelumnya

Contoh gambar:

masukkan deskripsi gambar di sini

Dalam Gambar ini saya ingin menghubungkan titik (8 konektivitas) yang kurang dari katakan jarak 40 piksel sehingga saya akan mendapatkan tangan kiri sebagai satu kontur

Tujuan saya adalah hanya mendapatkan kontur tangan (saya tidak peduli dengan daerah lain)

Pulau Roney
sumber
dengan tangan yang Anda maksud sebenarnya adalah lengan. tidak bisakah Anda menyesuaikan warna yang Anda gunakan untuk mendeteksi kulit agar sesuai dengan warna kulit Anda?
waspinator
Saya telah melakukan itu dan hasilnya bagus (Ketika kulit saya menyala). Jadi pada malam hari datang seperti yang ditunjukkan. Bagaimanapun saya berpikir bahwa mungkin ada beberapa metode untuk menghubungkan gumpalan terdekat.
Pulau Roney
Terkait dengan dsp.stackexchange.com/q/2588/590
Chris
Selamat datang di stack exchange. SE bukan forum! Ini bukan jawaban untuk pertanyaan itu. Jika Anda memiliki pertanyaan tentang pertanyaan - tulis ini sebagai komentar.
Dipan Mehta
bagaimana Anda mendeteksi kulit?
nkint

Jawaban:

10

Jika Anda tidak khawatir tentang kecepatan atau kontur tangan yang tepat, di bawah ini adalah solusi sederhana.

Metodenya seperti ini: Anda mengambil setiap kontur dan menemukan jarak ke kontur lainnya. Jika jaraknya kurang dari 50, mereka berada di dekatnya dan Anda menyatukannya. Jika tidak, mereka dianggap berbeda.

Jadi memeriksa jarak ke setiap kontur adalah proses yang memakan waktu. Butuh beberapa detik. Jadi tidak mungkin Anda bisa melakukannya secara real time.

Juga, untuk bergabung dengan kontur, saya menempatkan mereka dalam satu set dan menggambar lambung cembung untuk set itu. Jadi hasil yang Anda dapatkan sebenarnya adalah lambung cembung, bukan tangan asli.

Di bawah ini adalah kode saya di OpenCV-Python. Saya belum pergi untuk optimasi apa pun, hanya ingin bekerja, itu saja. Jika itu memecahkan masalah Anda, pergi untuk optimasi.

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)

Di bawah ini adalah hasil yang saya dapatkan:

masukkan deskripsi gambar di sini

masukkan deskripsi gambar di sini

Abid Rahman K
sumber
Bagaimana ini bisa dilakukan di c ++? Saya memiliki hingga bagian findContour tapi setelah itu saya tidak bisa mendapatkan kontur untuk membungkus poligon seperti yang ditunjukkan di atas (sebagai lawan dari persegi panjang yang membatasi).
Elionardo Feliciano
Saya menghargai pendekatan Anda dan mencoba menerapkan pada kasus saya, tetapi sayangnya itu sangat lambat pada Python (meskipun laptop saya memiliki Core i7QM dan 8GB RAM). Saya menggunakan MSER untuk mendeteksi daerah dan sekarang perlu menentukan pasangan wilayah mana yang "berdekatan", saya mencoba algoritme Anda dengan ambang batas 10 ... Butuh bertahun-tahun untuk mengembalikan daerah yang berdekatan.
Jim Raynor
4

Untuk memperbaiki masalah konektivitas, Anda dapat mencoba operasi tutup:

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

Saya ragu bahwa ini akan menghasilkan hasil yang Anda inginkan, tetapi Anda dapat mencobanya.

bjoernz
sumber
2

Sepertinya Anda "men-overegmentasikan" gambar Anda. Operasi morfologis, seperti yang disarankan bjnoernz, akan membantu. Secara khusus, pendekatan watershedding harus lebih dekat dengan apa yang Anda inginkan daripada hanya memeriksa jarak (seperti pada contoh python di atas). Lihat http://cmm.ensmp.fr/~beucher/wtshed.html .

Kotor
sumber