Python OpenCV confusion clarifications - Article 2
Mohammed Ismail
Senior Instrumentation & Control Engineer at Abuqir Fertilizers company, freelancer: Python developer, Data scientist
Now you are the owner of a pomegranates agricultural farm. You are hiring robots to deploy site surveillance in order to gather reports about the pomegranates distribution and statues. We can utilise the data to derive much features and precise classifications for the products of the farm based upon datasets actually constructed upon images. How will robots detect the pomegranates?
Let's start with a simple picture from our farm! Red colour with its derivatives is the unique feature of the pomegranates. Filtering the image to detect red objects only may accomplish the required task.
OpenCV function inRange() scans for objects with colours laying in a range between lower value and upper value, then it outputs a binary image (Refer to Article 1 to revise about binary images). White pixels are representing locations with colours found in the targeted range, while black pixels are representing locations with colours outside the targeted range. (Follow the appendix below to know how to use the mask binary image to form data stamps or indication)
The last step to get our scan image for pomegranates is to deploy masked bitwise_and() on our original image. Now we have detection of red objects only. Sometimes the story is not so simple and the produced image needs some more processing and filtering for more accuracy but for our example it's OK. It's recommended to use HSV colour space instead of RGB/BGR colour spaces as HSV can recognise the shades and illumination effects on the objects colours.
Here is the code:
#numpy and opencv libraries must be imported first #------------------------------------------------- img0 = cv2.imread('romman.jpg', cv2.IMREAD_UNCHANGED) hiRed = np.array([50,50,255]) #50,50,255 loRed = np.array([0,0,10]) #0,0,10 mask = cv2.inRange(img0, loRed, hiRed) maskedImg = cv2.bitwise_and(img0, img0, mask = mask) cv2.imshow('Original', img0) cv2.imshow('Mask Image', mask) cv2.imshow('Masked Image', maskedImg)
Our robot is movable along wide sections across the farm and it's building a life video report. This is the source video.
Videos are just consequent image frames per second.
cap = cv2.VideoCapture('romman.mp4') while(True): ret, frame = cap.read() hiRed = np.array([50,50,255]) #50,50,255 loRed = np.array([0,0,10]) #0,0,10 mask = cv2.inRange(frame, loRed, hiRed) maskedFrame = cv2.bitwise_and(frame, frame, mask = mask) cv2.imshow('Original', frame) cv2.imshow('Mask Image', mask) cv2.imshow('Masked Image', maskedFrame) if cv2.waitKey(1) & 0xFF == ord('q'): break cap.release() cv2.destroyAllWindows()
Appendix
The masking binary image as we know consists of pure white pixels indicating existence of scanned objects, and pure black pixels telling us no targeted objects detected. If we study the histogram of the image, we can make estimate of density, distribution, or any other potential feature.
We will use matplotlib python library for drawing histograms.
import matplotlib.pyplot as plt img = cv2.imread("romMask.jpg", cv2.IMREAD_GRAYSCALE) img = img.ravel() plt.hist(img) plt.show()