Улучшение угла обнаружения лампы с OpenCV - PullRequest
1 голос
/ 05 марта 2020

Я использую следующий код для обнаружения ярко освещенной лампы. Освещенность может отличаться. Я использую следующий код, чтобы обнаружить то же самое.

img = cv2.imread("input_img.jpg")
rgb = img.copy()
img_grey = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
while True:

    th3 = cv2.adaptiveThreshold(img_grey, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, \
                                cv2.THRESH_BINARY, 11, 2)

    cv2.imshow("th3",th3)

    edged = cv2.Canny(th3, 50, 100)
    edged = cv2.dilate(edged, None, iterations=1)
    edged = cv2.erode(edged, None, iterations=1)

    cv2.imshow("edge", edged)

    cnts = cv2.findContours(edged.copy(), cv2.RETR_TREE,
                            cv2.CHAIN_APPROX_SIMPLE)
    cnts = imutils.grab_contours(cnts)
    areaArray = []

    for i, c in enumerate(cnts):
        area = cv2.contourArea(c)
        areaArray.append(area)
    sorteddata = sorted(zip(areaArray, cnts), key=lambda x: x[0], reverse=True)

    thirdlargestcontour = sorteddata[2][1]
    x, y, w, h = cv2.boundingRect(thirdlargestcontour)
    cv2.drawContours(rgb, thirdlargestcontour, -1, (255, 0, 0), 2)

    cv2.rectangle(rgb, (x, y), (x + w, y + h), (0, 255, 0), 2)

    cv2.imshow("rgb", rgb)
    if cv2.waitKey(1) == 27:
        break

Приведенный выше код работает, но,

  1. Он дает только прямоугольник, который охватывает лампу. Как точно определить четыре угловые точки лампы?
  2. Как улучшить обнаружение? в данный момент я выбираю третий по величине контур, который не гарантирует, что он всегда будет лампой, когда окружающая среда создает проблемы?

enter image description here

ApproxPolydp работает, когда контур завершен, но если контур неполный, ApproxPolydp не возвращает правильную координату. Например, на следующем рисунке апполпидп возвращает неправильные координаты.

enter image description here

1 Ответ

0 голосов
/ 05 марта 2020

Вот один из способов сделать это в Python / OpenCV.

  • Чтение входного изображения и преобразование в оттенки серого
  • Использование адаптивного порогового значения для получения толстого контура области лампы
  • Поиск контуров
  • Отфильтруйте контуры по области, чтобы удалить посторонние области и оставьте только большее из двух (внутренний и внешний контуры пороговой области)
  • Получите периметр
  • Установите периметр на многоугольник, который должен быть четырехугольником с правильным выбором аргументов.
  • Нарисуйте контур (красный) и многоугольник (синий) поверх копии входного изображения как результат

Ввод:

enter image description here

import cv2
import numpy as np

# load image
img = cv2.imread("lamp.jpg")

# convert to gray
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# threshold image
thresh = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 11, 10)
thresh = 255 - thresh

# find contours
cntrs = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
cntrs = cntrs[0] if len(cntrs) == 2 else cntrs[1]

# Contour filtering -- remove small objects and those that are too large
# Keep the larger of the two contours (inner and outer contours from thresh)
area_thresh = 0
for c in cntrs:
    area = cv2.contourArea(c)
    if area > 200 and area > area_thresh:
        big_contour = c
        area_thresh = area

# draw big_contour on image in red and polygon in blue and print corners
results = img.copy()
cv2.drawContours(results,[big_contour],0,(0,0,255),1)
peri = cv2.arcLength(big_contour, True)
corners = cv2.approxPolyDP(big_contour, 0.04 * peri, True)
cv2.drawContours(results,[corners],0,(255,0,0),1)
print(len(corners))
print(corners)

# write result to disk
cv2.imwrite("lamp_thresh.jpg", thresh)
cv2.imwrite("lamp_corners.jpg", results)

cv2.imshow("THRESH", thresh)
cv2.imshow("RESULTS", results)
cv2.waitKey(0)
cv2.destroyAllWindows()


пороговое изображение:

enter image description here

Результат Изображение:

enter image description here

Угловые координаты:

[[[233 145]]

 [[219 346]]

 [[542 348]]

 [[508 153]]]


...