Detection of rust with OpenCV (Python)

asked 2017-11-15 13:05:53 -0600

Camerutttt gravatar image

updated 2017-11-15 14:23:05 -0600

LBerger gravatar image

We are currently working on a project whereby we have to detect rust on a building by taking pictures (using a drone). We then plan to use OpenCV to detect the colour of rust (brownish-orange) from the photographs taken.

However, we are facing difficulties with the color detection whereby other shades of color (yellow) are being detected as well and also not all shades of rust are being detected. So how can we solve this problem?

This is the link that we are using as guidance for our rust detection procedure: Colour Detection

This is the photograph that we want to detect rust: Rust Image

So this is the 1st version of our code, we selected the lightest and darkest shade of rust using GIMP and we set the BGR as our boundaries as shown in the code:

import cv2 
import numpy as np

#Read the Rust Photograph
img = cv2.imread('/home/brendanloe/Downloads/img.jpeg', 1)

#Set the boundary for the shade of rust 
boundaries = [ ([58, 57, 101], [76, 95, 162]) ]

#Highlight out the shade of rust
for (lower, upper) in boundaries:
    lower = np.array(lower, dtype = "uint8")
    upper = np.array(upper, dtype = "uint8")
    mask = cv2.inRange(img, lower, upper)
    output = cv2.bitwise_and(img, img, mask = mask)

#Show the shade of rust that is highlighted
cv2.imshow("images", np.hstack([img, output]))
cv2.waitKey(0)

Here is the result after running the code: Result 1

Hence we decided to come up with a 2nd version, with more boundaries for the shades of rust which couldn't be captured from the 1st version:

import cv2
import numpy as np

#Read the Rust Photograph
img = cv2.imread('/home/brendanloe/Downloads/img.jpeg', 1)

#Set different boundaries for different shades of rust
boundaries1 = [ ([58, 57, 101], [76, 95, 162]) ]
boundaries2 = [ ([26, 61, 111], [81, 144, 202]) ]
boundaries3 = [ ([44, 102, 167], [115, 169, 210]) ]

#Highlight out the shades of rust
for (lower1, upper1) in boundaries1:
    lower1 = np.array(lower1, dtype = "uint8")
    upper1 = np.array(upper1, dtype = "uint8")
    mask = cv2.inRange(img, lower1, upper1)
    output1 = cv2.bitwise_and(img, img, mask = mask)

for (lower2, upper2) in boundaries2:
    lower2 = np.array(lower2, dtype = "uint8")
    upper2 = np.array(upper2, dtype = "uint8")
    mask = cv2.inRange(img, lower2, upper2)
    output2 = cv2.bitwise_and(img, img, mask = mask)

for (lower3, upper3) in boundaries3:
    lower3 = np.array(lower3, dtype = "uint8")
    upper3 = np.array(upper3, dtype = "uint8")
    mask = cv2.inRange(img, lower3, upper3)
    output3 = cv2.bitwise_and(img, img, mask = mask)

#Combine the 3 different masks with the different shades into 1 image file
final = cv2.bitwise_or(output1, output2, output3)
cv2.imshow("final", final)
cv2.waitKey(0)

Here is the result after running the 2nd version of the code: Result 2

With the 2nd version, we were able to capture more shades of rust. However, not all the shades of rust were fully captured and the surroundings like trees and "parking" painting on the ground were captured as well.

Ideally, we want to program in a way where opencv automatically detect the rust when different photos of rust ... (more)

edit retag flag offensive close merge delete

Comments

1

you probably should do this in hsv color space, not bgr

berak gravatar imageberak ( 2017-11-15 16:11:07 -0600 )edit

How do I define the range for a certain pixel in BGR? From my photograph, I used GIMP and chose a particular pixel and it gives me a BGR value of 58 57 101. After converting it to HSV using the cv2.cvtColor function, I got 179 111 101 as the HSV value. How do I define the range for this particular HSV value?

Camerutttt gravatar imageCamerutttt ( 2017-11-16 03:16:04 -0600 )edit