--- a
+++ b/CvImage.py
@@ -0,0 +1,126 @@
+import cv2
+import imutils
+import numpy as np
+from math import sqrt
+
+def abs (n):
+  if n >= 0:
+    return n
+  return abs((-1 * n))
+
+class CvImage:
+  def __init__ (self, image, name):
+    self.__name = name
+    self.__originalImage = image
+    self.__image = image
+    self.__contours = False
+    self.__contoursFeatures = False
+  
+  def getName (self):
+    return self.__name
+
+  def getOriginalImage (self):
+    return self.__originalImage
+
+  def getImage (self):
+    return self.__image
+
+  def drawCircle (self, center, radious = 1, color = (0, 255, 0), thickness = 2):
+    cv2.circle(self.__image, center, radious, color, thickness)
+
+  def drawContours (self, contours, color = (0, 255, 0), thickness = 2):
+    cv2.drawContours(self.__image, contours, -1, color, thickness)
+
+  def __show (self, name, image):
+    cv2.imshow(name, image)
+    cv2.waitKey(0)
+
+  def showOriginal (self):
+    self.__show(self.__name + "-original", self.getOriginalImage())
+  
+  def show (self):
+    self.__show(self.__name, self.__image)
+
+  def morphOperations (self, kernelSize = 3):
+    # Open and close morph operations
+    kernel = np.ones((kernelSize, kernelSize),np.uint8)
+    self.__image = cv2.morphologyEx(self.__image, cv2.MORPH_OPEN, kernel)
+    self.__image = cv2.morphologyEx(self.__image, cv2.MORPH_CLOSE, kernel)  
+
+  def hsvFilter (self, lowerHSV, higherHSV):
+    # Convert to HSV
+    self.__image = cv2.cvtColor(self.__image, cv2.COLOR_BGR2HSV)
+
+    # InRange filter
+    self.__image = cv2.inRange(self.__image, lowerHSV, higherHSV)
+    
+
+  def getContours(self):
+    if self.__contours == False:
+      self.__contours = self.__findCountours()
+    return self.__contours
+
+  def getContoursFeatures(self, n = 5):
+    if self.__contoursFeatures == False:
+      self.__contoursFeatures = self.__findContoursFeatures(n)
+    return self.__contoursFeatures
+
+  def gray2bgr (self):
+    self.__image = cv2.cvtColor(self.__image, cv2.COLOR_GRAY2BGR)
+
+  def bgr2gray (self):
+    self.__image = cv2.cvtColor(self.__image, cv2.COLOR_BGR2GRAY)
+
+  def __findCountours(self):
+    # ConvertToGrayScale and filter
+    gray = cv2.bilateralFilter(self.__image, 11, 17, 17)
+    
+    # Edge algoritm
+    edged = cv2.Canny(gray, 30, 200)
+
+    cnts = cv2.findContours(edged.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
+    cnts = imutils.grab_contours(cnts)
+
+    # Sort by larger areas
+    cnts = sorted(cnts, key = cv2.contourArea, reverse = True)
+    return cnts
+
+  def __findContoursFeatures (self, minArea):
+    contoursFeatures = []
+    cnts = self.getContours()
+    for i in range(0, len(cnts)):
+      if cv2.contourArea(cnts[i]) >= minArea:
+        # Compute the center of the contour
+        M = cv2.moments(cnts[i])
+        cx = int(M["m10"] / M["m00"])
+        cy = int(M["m01"] / M["m00"])
+
+        # Get some basic features
+        perimeter = cv2.arcLength(cnts[i], True)
+        epsilon = 0.1*perimeter
+        approx = cv2.approxPolyDP(cnts[i],epsilon,True)
+
+        # Calculate eccentricity
+        (x, y), (MA, ma), angle = cv2.fitEllipse(cnts[i])
+        a = ma/2
+        b = MA/2
+        
+        if (a > b):
+          eccentricity = sqrt(pow(a, 2)-pow(b, 2))
+          eccentricity = round(eccentricity/a, 2)
+        else:
+          eccentricity = sqrt(pow(b, 2)-pow(a, 2))
+          eccentricity = round(eccentricity/b, 2)
+
+        # Append features
+        contoursFeatures.append({
+          "area": cv2.contourArea(cnts[i]),
+          "perimeter": perimeter,
+          "eccentricity": eccentricity,
+          "centroid": (cx, cy),
+          "approxDp": np.squeeze(approx),
+          "convexHull": np.squeeze(cv2.convexHull(cnts[i]))
+        })
+      else:
+        break
+    return contoursFeatures
\ No newline at end of file