dimanche 27 mars 2016

Designing a class that does not need to maintain state

I am trying to make an application that would need to extract the major colours of an image. So I made a class that has a few functions which are used to identify the major of colours(Like generate histogram, flatten image, make clusters of colors etc.). These functions are unrelated to each other, but together they achieve a certain functionality. But I am not sure how to actually design the class. Right now I am taking an image(or path to image) as an input parameter in Constructor/SetImage function. But I figured that attaching this image to the state of class is of no use. The basic functionality is just to feed it an image and get something in return. I felt it might be better if i wrote just a function, but I would like to connect the other functions with the main used function somehow as well. I thought maybe i should write all of them as static, but I am not sure, if that would be the correct way to do it.

I am not sure if this case falls into a design pattern(which i have read, or maybe i couldn't think a way to pout this into that). Not sure what the best convention would be.

What I want to do is, Initialize the class, and then call a function and get the results. I could surely write something simple as that, explicitly passing arguments, and stuff. But I want to make sure I don't miss out knowing the best practices and conventions. I am currently writing the code in Python, but I don't want a python centric solution(like maybe do something by implementing the call method or something.)

Heres the code I have right now.

class colorIdentifier(object):
    def __init__(self,**kwargs):
        self.img = None
        self.hist = None

    def setImg(self, img):
        if(type(img) is str):
            self.img = cv2.imread(img)
            self.img = cv2.cvtColor(self.img, cv2.COLOR_BGR2RGB)
        else:
            self.img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

        h, w, _ = self.img.shape
        w_new = int(100 * w / max(w, h) )
        h_new = int(100 * h / max(w, h) )

        self.img = cv2.resize(self.img, (w_new, h_new))

    def flatten(self,img):
        image_array = self.img.reshape((self.img.shape[0] * self.img.shape[1], 3))
        # Clusters the pixels
        self.clt = KMeans(n_clusters = 3)
        self.clt.fit(image_array)


    def getClusters(self):
        clt = self.clt
        # Finds how many pixels are in each cluster
        self.hist = self.__centroid_histogram(clt)

        # Sort the clusters according to how many pixel they have
        zipped = zip (self.hist, clt.cluster_centers_)
        zipped.sort(reverse=True, key=lambda x : x[0])
        self.hist, clt.cluster_centers = zip(*zipped)

    def __centroid_histogram__(self,clt):
        # grab the number of different clusters and create a histogram
        # based on the number of pixels assigned to each cluster
        numLabels = np.arange(0, len(np.unique(clt.labels_)) + 1)
        (hist, _) = np.histogram(clt.labels_, bins = numLabels)

        # normalize the histogram, such that it sums to one
        hist = hist.astype("float")
        hist /= hist.sum()

        # return the histogram
        return hist

Aucun commentaire:

Enregistrer un commentaire