2016-05-16 20 views
2

Ich versuche, die Kmeans von opencv anwenden, um das Bild im HSV-Farbraum zu segmentieren.Python + OpenCV Farbsegmentierung mit Kmeans

def leftOffset(src, p_countours): 
    height, width, size = src.shape 

    p_width = width/p_countours 
    o_left = src[0:height, 0:p_width] 

    HSV_img = cv2.cvtColor(o_left, cv2.COLOR_BGR2HSV) 
    hue = HSV_img[0] 
    hue = np.float32(HSV_img) 

    # Define criteria = (type, max_iter = 10 , epsilon = 1.0) 
    criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 10, 1.0) 

    # Set flags (Just to avoid line break in the code) 
    flags = cv2.KMEANS_RANDOM_CENTERS 

    # Apply KMeans 
    compactness,labels,centers = cv2.kmeans(hue,2,criteria,10,flags) 

    centers = np.uint8(centers) 
    res = centers[labels.flatten()] 
    res2 = res.reshape((hue.shape)) 
    cv2.imshow("o_left", hue) 
    cv2.waitKey(0) 

Ich bin jetzt in der Lage, den KMeans Algorithmus auf die HSVImage [0] mit K = 2, und wie kann ich nach dem Ergebnis ein Bild wie Schwelle erhalten bewerben?

Dank

die Frage zu klären: Ich habe farbbasierten Captchas, und ich möchte die jeweils Ziffern Segment.

Das Bild ist wie 6

1

Ich werde k-Mittel-Methode verwenden, um die dominante Farbe, um herauszufinden, und das Segment der Innen Ziffern.

+0

ich nicht ganz verstehe die Frage kann. Kannst du das bitte klären, indem du ein Bild einfügst? – tfv

+0

@tfv Ich habe 2 Testbilder hinzugefügt – Mix

+0

Welche Version von opencv verwenden Sie? –

Antwort

3

Darf ich eine konventionelle Alternative vorschlagen? Wenn Sie zuerst die sehr dunklen und hellen Bereiche entfernen, können Sie sich vielleicht einfach auf den häufigsten Wert der Farbtonkomponente verlassen, der aus dem Histogramm berechnet wird.

Beachten Sie, dass die Grenzen der Zahlen nie absolut genau sein werden, da Farben in der Umgebung ähnlich sind.

Außerdem könnten Sie nur den maximalen Blob auswählen (je nach Größe), um verbleibende kleine Blobs außerhalb zu unterdrücken.

Ergebnisse:

enter image description here

Code:

import cv2 
import numpy as np 
from matplotlib import pyplot as plt 


img = cv2.imread('image1.jpg') 

#get rid of very bright and very dark regions 
delta=30 
lower_gray = np.array([delta, delta,delta]) 
upper_gray = np.array([255-delta,255-delta,255-delta]) 
# Threshold the image to get only selected 
mask = cv2.inRange(img, lower_gray, upper_gray) 
# Bitwise-AND mask and original image 
res = cv2.bitwise_and(img,img, mask= mask) 

#Convert to HSV space 
HSV_img = cv2.cvtColor(res, cv2.COLOR_BGR2HSV) 
hue = HSV_img[:, :, 0] 

#select maximum value of H component from histogram 
hist = cv2.calcHist([hue],[0],None,[256],[0,256]) 
hist= hist[1:, :] #suppress black value 
elem = np.argmax(hist) 
print np.max(hist), np.argmax(hist) 

tolerance=10 
lower_gray = np.array([elem-tolerance, 0,0]) 
upper_gray = np.array([elem+tolerance,255,255]) 
# Threshold the image to get only selected 
mask = cv2.inRange(HSV_img, lower_gray, upper_gray) 
# Bitwise-AND mask and original image 
res2 = cv2.bitwise_and(img,img, mask= mask) 


titles = ['Original Image', 'Selected Gray Values', 'Hue', 'Result'] 
images = [img, res, hue, res2] 
for i in xrange(4): 
    plt.subplot(2,2,i+1),plt.imshow(images[i],'gray') 
    plt.title(titles[i]) 
    plt.xticks([]),plt.yticks([]) 
plt.show() 
2

1) Wenn Sie nur die dominante Farbe finden müssen, warum finden Sie nicht die Histogramme jedes Farbkanals? Finden Sie den dominanten Kanal und segmentieren Sie dann nur diesen Kanal mit otsu? Zum Beispiel, wenn ich nur den Farbton schwelle, kann ich schöne Ergebnisse bekommen. K-Mittel könnte ein Overkill für diese Aufgabe sein:

import cv2 
import numpy as np 
import matplotlib.pylab as plt 

## Simple Otsu over hue 
six = cv2.imread('7zovC.jpg') 

##convert to hsv 
hsv = cv2.cvtColor(six, cv2.COLOR_BGR2HSV) 
hue = hsv[:, :, 0] 

binary_img = cv2.threshold(hue, 128, 255, cv2.THRESH_OTSU) 

plt.figure() 
plt.imshow(binary_img*255) 
plt.show() 

2) Warum alle Kanäle nicht für Clustering verwenden, anstatt Farbton nur? Was Sie brauchen, ist Clustering -> Farbquantisierung dieses link sollte nützlich sein. Dies ist für opencv Version> 3.0.0

Hinweis für Python 2.4.11, hat cv2.kmeans eine leicht Schnittstelle Unterschied und man konnte diese statt:

def color_quantize(img, K): 
    Z = img.reshape((-1, 3)) 

    # convert to np.float32 
    Z = np.float32(Z) 

    # define criteria, number of clusters(K) and apply kmeans() 
    criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 10, 1.0) 
    ret, label, center = cv2.kmeans(Z, 2, criteria, 10, cv2.KMEANS_RANDOM_CENTERS) 

    # Now convert back into uint8, and make original image 
    center = np.uint8(center) 
    res = center[label.flatten()] 
    quantized_img = res.reshape((img.shape)) 

    label_img = label.reshape((img.shape[:2])) 
    return label_img, quantized_img 



six = cv2.imread('7zovC.jpg') 


##convert to hsv 
hsv = cv2.cvtColor(six, cv2.COLOR_BGR2HSV) 

K = 2 
label_img, six_q = color_quantize(hsv, K) 



plt.figure() 
plt.imshow(label_img) 

plt.show() 

Meine Ergebnisse für Farbquantisierung nicht beeindruckend waren .