我目前正在一个项目中,通过图像处理来测量明渠中的水位。我的主要问题是由于实验室条件的限制,我必须处理有问题的图像。 (即照明不良,背景不良等)。
目前这是我拥有的最好的图像,将来我会得到更好的图像,但是现在这就是我正在使用的图像。
由于图片中有太多内容,我决定过滤蓝色以绘制一些轮廓,然后选择需要处理的轮廓。但是我似乎无法很好地绕过它以检测每个蓝色矩形。我还尝试过仅对图像进行灰度处理,然后绘制轮廓,这似乎效果更好,但还不够。为了进行测量,我计划使用霍夫变换。
我的问题是;我是完全犯错了吗,还是我当前使用的图像根本不够好而无法处理?我应该尝试其他库或语言吗?这是我当前的代码;
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()
答案 0 :(得分:1)
不要让它太复杂。我用了你的一些代码。
PS:我只能为您提供帮助,让您专注于尝试测量水位。但最后我会给你一个提示
import numpy as np
import cv2
def show(img):
cv2.imshow('a',img)
cv2.waitKey()
cv2.destroyAllWindows()
mask = cv2.imread("azC2r.jpg",0)
img = cv2.imread("azC2r.jpg")
print('Image shape: {}'.format(img.shape))
ret,thresh = cv2.threshold(mask,50,255,cv2.THRESH_BINARY)
thresh = cv2.blur(thresh,(7,7))
thresh[thresh<254]=0
kernel = np.ones((7,7))
thresh = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel)
kernel = np.ones((9,9))
thresh = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel)
thresh = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel)
im2, contours,_ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contours = [cnt for cnt in contours if cv2.contourArea(cnt)<100000]
cv2.drawContours(img, contours, -1, (0,255,0), 3)
# Thank to this snippet to
# https://stackoverflow.com/questions/37912928/fill-the-outside-of-contours-opencv
stencil = np.zeros(img.shape).astype(img.dtype)
color = [255, 255, 255]
cv2.fillPoly(stencil, contours, color)
img = cv2.bitwise_and(img, stencil)
# END of snippet
img[np.where(np.all(img==[255,255,255],axis = 2))]=[0,0,0]
show(img)
我做了什么?: 我将在图片中为您解释。
灰度阈值
模糊阈值以填充行
所有非纯白色[255,255,255]都变为[0,0,0]
用形态学技巧摆脱单独的小颗粒
绘制特定大小的轮廓-摆脱太大和太小的
最后使用cv2.polly清除国家/地区以外的所有内容,并将其变为黑色。请参阅第一张图片以获取结果
就水位测量而言,我并不十分了解,也不想深入研究,但是也许您可以使用sobely
sobely = cv2.Sobel(img,cv2.CV_64F,0,1,ksize=3)