I am currently working on a project to measure water levels in an open channel with image processing. My main issue is that I have to work on rather problematic images because of our lab conditions. ( i.e. bad lighting, bad background etc.)
Currently this is the best image I have, I will get better ones in the future but for now this is what I'm working with.
Since there's so much going on in the picture, I decided to filter blue color to draw some contours and pick the ones I need to work on. But I can't seem to get around it well enough to detect every blue rectangle. I've also tried to just grayscale the image and then draw contours, which seems to work better but still not enough. For measurement I'm planning on using Hough Transform.
My question is; am I approaching this completely wrong, or the image I'm currently working with is simply not good enough to work on? Should I try different libraries or languages? Here's my current code;
from imutils import perspective
from imutils import contours
import numpy as np
import imutils
import cv2 as cv
blueLow = np.array([90, 50, 20])
blueHigh = np.array([130, 255, 255])
img = cv.imread("10ltsn.png")
imgHSV = cv.cvtColor(img, cv.COLOR_BGR2HSV)
mask = cv.inRange(imgHSV, blueLow, blueHigh)
##imgray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
##kernelOpen = np.ones((5,5))
##kernelClose = np.ones((20,20))
##maskOpen = cv.morphologyEx(mask, cv.MORPH_OPEN, kernelOpen)
##maskClose = cv.morphologyEx(maskOpen, cv.MORPH_CLOSE, kernelClose)
##imgray = cv.GaussianBlur(imgray, (5,5), 0)
##imgray = cv.bilateralFilter(imgray,9,75,75)
edge = cv.Canny(mask, 50, 200)
edge = cv.dilate(edge, None, iterations=1)
edge = cv.erode(edge, None, iterations=1)
cnt = cv.findContours(edge.copy(), cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
cnt = imutils.grab_contours(cnt)
##(cnt, _) = contours.sort_contours(cnt)
for k in cnt:
if cv.contourArea(k) < 1000:
continue
main = img.copy()
box = cv.minAreaRect(k)
box = cv.boxPoints(box)
box = np.array(box, dtype="int")
box = perspective.order_points(box)
cv.drawContours(main, [box.astype("int")], -1, (0, 255, 0), 1)
for (x, y) in box:
cv.circle(main, (int(x), int(y)), 5, (0, 0, 255), -1)
cv.imshow("main", main)
cv.waitKey(0)
##cv.imshow("img", img)
##cv.imshow("mask", mask)
##cv.imshow("mask2", mask2)
##cv.imshow("edge", edged)
##cv.imshow("maskClose", maskClose)
##cv.imshow("maskOpen", maskOpen)
##cv.waitKey(0)
cv.destroyAllWindows()