image segmentation using kmeans clustering python opencv
Question: I've been trying to achieve similar results to this [MATLAB
code](http://www.mathworks.com/help/images/examples/color-based-segmentation-
using-k-means-clustering.html) which gives me the result I am looking for,
however, I am trying to achieve that using OpenCV 3 + Python.

Here's a similar implementation in OpenCV 3 + Python:

    
    
    import cv2
    import numpy as np
    
    class Segment:
        def __init__(self,segments=5):
            #define number of segments, with default 5
            self.segments=segments
    
        def kmeans(self,image):
            image=cv2.GaussianBlur(image,(7,7),0)
            vectorized=image.reshape(-1,3)
            vectorized=np.float32(vectorized) 
            criteria=(cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 10, 1.0)
            ret,label,center=cv2.kmeans(vectorized,self.segments,None,criteria,10,cv2.KMEANS_RANDOM_CENTERS)
            res = center[label.flatten()]
            segmented_image = res.reshape((image.shape))
            return label.reshape((image.shape[0],image.shape[1])),segmented_image.astype(np.uint8)
    
    
        def extractComponent(self,image,label_image,label):
            component=np.zeros(image.shape,np.uint8)
            component[label_image==label]=image[label_image==label]
            return component
    
    if __name__=="__main__":
        import argparse
        import sys
        ap = argparse.ArgumentParser()
        ap.add_argument("-i", "--image", required = True, help = "Path to the image")
        ap.add_argument("-n", "--segments", required = False, type = int,
            help = "# of clusters")
        args = vars(ap.parse_args())
    
        image=cv2.imread(args["image"])
        if len(sys.argv)==3:
    
            seg = Segment()
            label,result= seg.kmeans(image)
        else:
            seg=Segment(args["segments"])
            label,result=seg.kmeans(image)
        cv2.imshow("segmented",result)
        result=seg.extractComponent(image,label,2)
        cv2.imshow("extracted",result)
        cv2.waitKey(0)
    

What I'm looking for is being able to extract A by itself and rectangle around
it by itself and the background by itself so I can manipulate them seperately.

Here you can see the original image + current output + desired output:

[![enter image description
here](http://i.stack.imgur.com/INlbZ.jpg)](http://i.stack.imgur.com/INlbZ.jpg)

Any idea how I can achieve that?


Answer: I can't do this right now, but there are some differences between your
implementation and Matlab's one that you should review:

  * **Color space** : Matlab's example works on L*a*b* and your implementation on BGR, specifically on 'a*' and 'b*' channels
  * **nClusters** : as you are not hard-coding it, I'm assuming you are using `segments=3` just like Matlab's examples does, right? Your default is 5...
  * **GaussianBlur** : I can't see any blur being applied on Matlab's example
  * **Attempts** : you are using `attempts=10`, while Matlab is only 3

