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 are opened, and also not to detect unwanted colors like our example as stated above.
Thank you for the help in advance.