import cv2
import numpy as np
import sys
import matplotlib.pyplot as plt

WIDTH=640
HEIGHT=480
ESC=27

def show(img, name=''):
    cv2.imshow(name, img)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

class CrackDetector(object):
    def __init__(self, filename):
        cv2.setUseOptimized(True)
        cv2.setNumThreads(2)
        self.img = cv2.imread(filename)
        self.origImg = np.copy(self.img)

    def gray(self):
        self.img = cv2.cvtColor(self.img, cv2.COLOR_BGR2GRAY)

    def normalize(self):
        minVal = np.min(self.img)
        maxVal = np.max(self.img)
        self.img = (255*((self.img - minVal)/(maxVal-minVal))).astype("uint8")

    def medianBlur(self, kernelSize=3):
        self.img = cv2.medianBlur(self.img, kernelSize)

    def canny(self, thresholdMin=40, thresholdMax=120, show=False, winName='canny'):
        def maxOnChange(value):
            print("Max:", value)

        def minOnChange(value):
            print("Min:", value)

        if show:
            winName = 'canny'
            cv2.namedWindow(winName)
            cv2.createTrackbar('max', winName, 0, 255, maxOnChange)
            cv2.setTrackbarPos('max', winName, thresholdMax)
            cv2.createTrackbar('min', winName, 0, 255, minOnChange)
            cv2.setTrackbarPos('min', winName, thresholdMin)
            edges = cv2.Canny(self.img, thresholdMin, thresholdMax)
            cv2.imshow(winName, edges)

            print("Press <ESC> to destroy the window!")
            while True:
                if cv2.waitKey(20) & 0xFF == ESC:
                    break
                maxVal = cv2.getTrackbarPos('max', winName)
                minVal = cv2.getTrackbarPos('min', winName)
                edges = cv2.Canny(self.img, minVal, maxVal)
                cv2.imshow(winName, edges)
        else:
            self.img = cv2.Canny(self.img, thresholdMin, thresholdMax)

    def show(self, name=''):
        cv2.imshow(name, self.img)
        cv2.waitKey(0)
        cv2.destroyAllWindows()

detector = CrackDetector(sys.argv[1])
detector.show('original')

# convert image to GRAY format
detector.gray()
detector.show('gray')

# median blur
detector.medianBlur()
detector.show('median')

# normalize
detector.normalize()
detector.show('normalize')

# edge detection
detector.canny(show=True, winName='Crack detector')

#ret, otsu = cv2.threshold(img, 20, 205, cv2.THRESH_BINARY | cv2.THRESH_OTSU)
#show(otsu, 'otsu')

@@ -34,16 +34,63 @@
 ort sys%0A
+import imutils%0Afrom imutils import perspective%0A
 import m
@@ -113,16 +113,16 @@
  as plt%0A
-
 %0AWIDTH=6
@@ -142,17 +142,16 @@
 %0AESC=27%0A
-%0A
 def show
@@ -1010,32 +1010,115 @@
 %22Min:%22, value)%0A%0A
+        minWidth = self.img.shape%5B0%5D/10%0A        minHeight = self.img.shape%5B1%5D/10%0A%0A%0A
         if show:
@@ -1952,32 +1952,29 @@
             
-self.img
+edges
  = cv2.Canny
@@ -2013,16 +2013,689 @@
 ldMax)%0A%0A
+        cv2.destroyAllWindows()%0A%0A        kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (10, 10))%0A        self.img = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)%0A%0A        boxes = %5B%5D%0A        #(_, contours, _) = cv2.findContours(edges.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)%0A        (_, contours, _) = cv2.findContours(self.img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)%0A        for c in contours:%0A            (w, h) = cv2.boundingRect(c)%5B2:%5D%0A            if w %3C minWidth and h %3C minHeight:%0A                continue%0A%0A            rect = cv2.minAreaRect(c)%0A            box = np.int0(cv2.boxPoints(rect))%0A            boxes.append(box)%0A        return boxes%0A%0A
     def 
@@ -3080,16 +3080,24 @@
 tection%0A
+boxes = 
 detector
@@ -3139,16 +3139,204 @@
 tector')
+%0Adetector.show('edge')%0A%0Aprint(boxes)%0Aoutput = np.copy(detector.origImg)%0Afor b in boxes:%0A    output = cv2.rectangle(output, tuple(b%5B0%5D), tuple(b%5B2%5D), (0, 255, 0), 4)%0A%0Ashow(output, 'output')
 %0A%0A#ret, 

Improve crack with close morphology operation