Ask Your Question
0

Using openCV python to detect concrete cracks

asked 2018-12-16 21:18:11 -0600

Esh gravatar image

Could anyone have an idea how i can isolate just the cracks from the image of a concrete surface. My input image is something like this:

image description

I am expecting my output to be something like this:

image description

I have tried canny edge detector but that gives me a broken contour. I tried dilation followed by erosion but that increases the width of crack segment in the binary image and that will be a problem as the width should not be changed. I need a closed contour of the crack without change in width. Can anyone point me in the right direction ?

edit retag flag offensive close merge delete

1 answer

Sort by ยป oldest newest most voted
2

answered 2018-12-17 03:10:15 -0600

VxW gravatar image

updated 2018-12-18 03:26:03 -0600

Hi,

an easy approach could be:

1) remove the inhomogeneous background illumination

apply a big gaussian bluring and substract the original image from the blured one.

image description

2) Apply e.g. e Sobel edge detection and a morphological close

image description

3) remove the noise using blob analysis (e.g. remove regions with small areas)

Best

Edit: In principle you have to convert the image between 0 and 1 before GaussianBlur. Additionally to get better results you also can apply a non-maximal suppression after sobel.

For a copy paste solution here we go:

(code is partly from here)

import cv2
import math
import numpy as np
import scipy.ndimage

def orientated_non_max_suppression(mag, ang):
    ang_quant = np.round(ang / (np.pi/4)) % 4
    winE = np.array([[0, 0, 0],[1, 1, 1], [0, 0, 0]])
    winSE = np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]])
    winS = np.array([[0, 1, 0], [0, 1, 0], [0, 1, 0]])
    winSW = np.array([[0, 0, 1], [0, 1, 0], [1, 0, 0]])

    magE = non_max_suppression(mag, winE)
    magSE = non_max_suppression(mag, winSE)
    magS = non_max_suppression(mag, winS)
    magSW = non_max_suppression(mag, winSW)

    mag[ang_quant == 0] = magE[ang_quant == 0]
    mag[ang_quant == 1] = magSE[ang_quant == 1]
    mag[ang_quant == 2] = magS[ang_quant == 2]
    mag[ang_quant == 3] = magSW[ang_quant == 3]
    return mag

def non_max_suppression(data, win):
    data_max = scipy.ndimage.filters.maximum_filter(data, footprint=win, mode='constant')
    data_max[data != data_max] = 0
    return data_max

# start calulcation
gray_image = cv2.imread(r'path ... ', 0)

with_nmsup = True #apply non-maximal suppression
fudgefactor = 1.3 #with this threshold you can play a little bit
sigma = 21 #for Gaussian Kernel
kernel = 2*math.ceil(2*sigma)+1 #Kernel size

gray_image = gray_image/255.0
blur = cv2.GaussianBlur(gray_image, (kernel, kernel), sigma)
gray_image = cv2.subtract(gray_image, blur)

# compute sobel response
sobelx = cv2.Sobel(gray_image, cv2.CV_64F, 1, 0, ksize=3)
sobely = cv2.Sobel(gray_image, cv2.CV_64F, 0, 1, ksize=3)
mag = np.hypot(sobelx, sobely)
ang = np.arctan2(sobely, sobelx)

# threshold
threshold = 4 * fudgefactor * np.mean(mag)
mag[mag < threshold] = 0

#either get edges directly
if with_nmsup is False:
    mag = cv2.normalize(mag, 0, 255, cv2.NORM_MINMAX)
    kernel = np.ones((5,5),np.uint8)
    result = cv2.morphologyEx(mag, cv2.MORPH_CLOSE, kernel)
    cv2.imshow('im', result)
    cv2.waitKey()

#or apply a non-maximal suppression
else:

    # non-maximal suppression
    mag = orientated_non_max_suppression(mag, ang)
    # create mask
    mag[mag > 0] = 255
    mag = mag.astype(np.uint8)

    kernel = np.ones((5,5),np.uint8)
    result = cv2.morphologyEx(mag, cv2.MORPH_CLOSE, kernel)

    cv2.imshow('im', result)
    cv2.waitKey()
edit flag offensive delete link more

Comments

I do not get the same crack width if i do this. My crack width is highly exaggerated after i apply the sobel operator. I need to have my crack width preserved.

My code:

blur = cv2.GaussianBlur(img, (75,75), 0)
sub = cv2.subtract(blur,img)
sobelx = cv2.Sobel(sub, cv2.CV_64F, 1, 0, ksize=3)
sobely = cv2.Sobel(sub, cv2.CV_64F, 0, 1, ksize=3)
outim = np.sqrt(sobelx ** 2 + sobely ** 2)
cv2.imshow('Output', outim)
Esh gravatar imageEsh ( 2018-12-17 19:40:39 -0600 )edit

I am trying to implement crack detection using openCV and python. I followed this tutorial and I have been able to identify the crack. However, it also detects edges and adds to false positives.

The original image is: Original Image

and the crack identified is: link text

I need to subtract the edges and just keep the crack highlighted.

piyushn gravatar imagepiyushn ( 2019-05-13 14:48:11 -0600 )edit

Question Tools

1 follower

Stats

Asked: 2018-12-16 21:18:11 -0600

Seen: 9,446 times

Last updated: Dec 18 '18