Mix Mix - 8 months ago 150
Python Question

Python + OpenCV color segmentation using Kmeans

I am trying to apply the kmeans from opencv in order to segment the image in HSV color space.

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)

# 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)

I am now able to apply the kmeans algorithm to the HSVImage[0] with K=2, and how can I get a image like threshold according to the result?


To clarify the question:
I have color-based captchas, and I want to segment each digits.

The image is like6


I am going to use k-means method to find out the dominant color and segment the digits inside.

tfv tfv

May I suggest a conventional alternative? I you get rid of the very dark and bright regions first, you may be able to simply rely on the most frequent value of the hue component calculated from the histogram.

Mind that the borders of the numbers will never be absolutely exact, since colours are similar in the surrounding.

Furthrmore, you could select the maximum blob only (according to size) to suppress remaining small blobs outside.


enter image description here


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
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)

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):