OpenCV рисование контуров различными методами на плохом изображении - PullRequest
0 голосов
/ 01 марта 2019

В настоящее время я работаю над проектом по измерению уровня воды в открытом канале с обработкой изображений.Моя главная проблема заключается в том, что мне приходится работать над довольно проблемными изображениями из-за наших лабораторных условий.(т.е. плохое освещение, плохой фон и т. д.) current sample image

В настоящее время это лучшее изображение, которое у меня есть, в будущем я получу лучшие, но пока это то, что яя работаю с.

Поскольку на снимке так много всего, я решил отфильтровать синий цвет, чтобы нарисовать некоторые контуры и выбрать те, над которыми мне нужно работать.Но я не могу обойти это достаточно хорошо, чтобы обнаружить каждый синий прямоугольник.Я также попытался просто отобразить изображение в градациях серого, а затем нарисовать контуры, что, кажется, работает лучше, но все же недостаточно.Для измерения я планирую использовать Hough Transform.

Мой вопрос;Я неправильно подхожу к этому, или изображение, с которым я сейчас работаю, просто недостаточно хорошо для работы?Стоит ли пробовать разные библиотеки или языки?Вот мой текущий код:

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()

1 Ответ

0 голосов
/ 02 марта 2019

Не делайте это слишком сложным.Я использовал часть вашего кода.

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)

Результат enter image description here

Что я сделал? Я объясню вамв изображениях.

Порог в оттенках серого

Threshold

Размытие на пороге для маскировкизаполненные строки

enter image description here

Все, что не чисто белое [255,255,255] становится [0,0,0]

enter image description here

Избавьтесь от отдельных мелких частичек с помощью морфологического трюка

enter image description here

Нарисуйте контуры определенного размера - избавьтесь от слишком больших и слишком маленьких

enter image description here

В конце cv2.polly избавьтесь от всего, что находится за пределами границ, и включите его в черный цвет.См. Первое изображение для результата

Что касается измерений уровня воды, я действительно не знаю и не хочу копаться в этом, но, возможно, вы можетеиграть с sobely

sobely = cv2.Sobel(img,cv2.CV_64F,0,1,ksize=3)

enter image description here

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...