2016-08-11 13 views
5

Obecnie robię wykrywanie kolejek na obrazach wyglądających jak ten, ale niektóre kropelki scalają się i tworzą nieregularne kształty (czerwone znaczniki na oryginalnym obrazie). Używam funkcji houghcircle w opencv do wykrywania kręgów. W przypadku tych nieregularnych kształtów funkcja może wykryć je tylko jako kilka małych okręgów, ale naprawdę chcę, aby program uwzględniał nieregularny kształt jako cały duży kształt i uzyskał duży okrąg, tak jak rysuję obraz wyjściowy.Wykrywanie nieregularnych kształtów za pomocą funkcji houghcircle pytka opencv

Original image

Output image

Mój kod wykryje wszystkie koła i inne średnice nich.

Oto mój kod:

def circles(filename, p1, p2, minR, maxR): 
# print(filename) 
img = cv2.imread(filename, 0) 
img = img[0:1000, 0:1360] 
l = len(img) 
w = len(img[1]) 

cimg = cv2.cvtColor(img,cv2.COLOR_GRAY2BGR) 

circles = cv2.HoughCircles(img, cv2.HOUGH_GRADIENT, 1, 25, 
          param1 = int(p1) ,param2 = int(p2), minRadius = int(minR), maxRadius = int(maxR)) 

diameter = open(filename[:-4] + "_diamater.txt", "w") 
diameter.write("Diameters(um)\n") 
for i in circles[0,:]: 
    diameter.write(str(i[2] * 1.29 * 2) + "\n") 

count = 0 
d = [] 
area = [] 
for i in circles[0,:]: 
    cv2.circle(cimg,(i[0],i[1]),i[2],(0,255,0),2) 
    cv2.circle(cimg,(i[0],i[1]),2,(0,0,255),3) 
    count += 1 
    d += [i[2]*2] 
    area += [i[2]*i[2]*pi*1.286*1.286] 

f = filename.split("/")[-1] 
cv2.imwrite(filename[:-4] + "_circle.jpg", cimg) 

# cv2.imwrite("test3/edge.jpg", edges) 
print "Number of Circles is %d" % count 

diaM = [] 
for i in d: 
    diaM += [i*1.286] 

bWidth = range(int(min(diaM)) - 10, int(max(diaM)) + 10, 2) 

txt = ''' 
Sample name: %s 
Average diameter(um): %f  std: %f 
Drop counts: %d 
Average coverage per drop(um^2): %f  std: %f 
''' % (f, np.mean(diaM), np.std(diaM), count, np.mean(area), np.std(area)) 

fig = plt.figure() 
fig.suptitle('Histogram of Diameters', fontsize=14, fontweight='bold') 
ax1 = fig.add_axes((.1,.4,.8,.5)) 
ax1.hist(diaM, bins = bWidth) 
ax1.set_xlabel('Diameter(um)') 
ax1.set_ylabel('Frequency') 
fig.text(.1,.1,txt) 
plt.savefig(filename[:-4] + '_histogram.jpg') 
plt.clf() 

print "Total area is %d" % (w*l) 
print "Total covered area is %d" % (np.sum(area)) 

rt = "Number of Circles is " + str(count) + "\n" + "Coverage percent is " + str(np.divide(np.sum(area), (w*l))) + "\n" 
return rt 

Odpowiedz

1

Jeśli nadal chcesz korzystać z funkcji HoughCircles, można po prostu sprawdzić, czy dwa okręgi pokrywają się i zrobić nowy krąg z nich.

+0

Próbowałem w ten sposób, ale nie jest wiele innych kręgów tuż obok siebie. Więc nie działa zbyt dobrze. Dzięki i tak. –

1

Możesz użyć do tego celu minEnclosingCircle. Znajdź kontury obrazu, a następnie zastosuj funkcję wykrywania kształtów jako kół.

Poniżej znajduje się prosty przykład z kodem C++. W twoim przypadku uważam, że powinieneś użyć kombinacji Hough-circles i minEnclosingCircle, ponieważ niektóre kręgi na twoim obrazie są bardzo blisko siebie, istnieje szansa, że ​​zostaną wykryte jako pojedynczy kontur.

wejścia obrazu:

input

koła:

output

Mat im = imread("circ.jpg"); 
Mat gr; 
cvtColor(im, gr, CV_BGR2GRAY); 
Mat bw; 
threshold(gr, bw, 0, 255, CV_THRESH_BINARY | CV_THRESH_OTSU); 

vector<vector<Point>> contours; 
vector<Vec4i> hierarchy; 
findContours(bw, contours, hierarchy, CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE, Point(0, 0)); 
for(int idx = 0; idx >= 0; idx = hierarchy[idx][0]) 
{ 
    Point2f center; 
    float radius; 
    minEnclosingCircle(contours[idx], center, radius); 

    circle(im, Point(center.x, center.y), radius, Scalar(0, 255, 255), 2); 
} 
0

Kiedy masz takie piękne dobrze rozdzielone i kontrastujące wzory, najprostszym sposobem byłoby wykorzystanie indeksów kształt . Zobacz this paper lub this poster. W obu przypadkach masz listę indeksów kształtu.

Dzięki kształtować indeksy, można co następuje:

  • binarne Wizerunek
  • połączony etykietowanie komponentów w celu oddzielenia każdego wzoru
  • indeksy kształt obliczeniowej (większość z nich korzysta z podstawowych środków)
  • Klasyfikuj wzór zgodnie z wartościami indeksów kształtu.

Jak w konkretnym przypadku okrągłe kształty są idealnie okrągłe, chciałbym użyć następujących indeksów kształt:

  • wahadłowością => używając tylko promienie, tak najłatwiej obliczyć i doskonały w swojej sprawie.
  • Przedłużenie/wydłużenie/rozciągnięcie za pomocą promieni => Idealne w twoim przypadku, ale obliczenia kulkowe z użyciem min nie są dostępne we wszystkich bibliotekach.
  • Deficyt izo-perymetryczny => bardzo łatwy do obliczenia, ale nieco mniej stabilny niż kołowość ze względu na obwód.

działa także w przypadku:

  • Gap wpisany dysk
  • Rozprzestrzenianie Morton
  • Deficyt
  • Rozszerzenie o średnicach