Opencv find rectangle python

OpenCV Detect Rectangle

OpenCV Detect Rectangle

This tutorial will discuss detecting rectangles using the findContours() and contourArea() function of OpenCV in Python.

Use the findContours() and contourArea() Function of OpenCV to Detect Rectangles in Images in Python

We can detect a rectangle present in an image using the findContours() function of OpenCV, and we can use the contourArea() function to sort different rectangles according to their area.

We can find the contours of the given image using the findContours() function of OpenCV, but we have to use a binary or black and white image inside the findContours() function.

To convert the given image into binary, we have to use the cvtColor() and threshold() function of OpenCV. The cvtColor() function is used to convert one color space into another, and we will use it to convert the BGR image to grayscale.

The threshold() function converts the grayscale image into binary with only two values, 0 and 255. See the code below.

import cv2 import numpy as np  img = cv2.imread('rectangle.jpg')  gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) thresh_img = cv2.threshold(gray_img, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1]  cnts = cv2.findContours(thresh_img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) cnts = cnts[0] if len(cnts) == 2 else cnts[1] for cnt in cnts:  approx = cv2.contourArea(cnt)  print(approx)  cv2.imshow('image', img) cv2.imshow('Binary',thresh_img) cv2.waitKey() 

detect rectangle

As shown in the output, the area of each rectangle is shown, and all the areas are different. Using these areas, we can sort the rectangles like we can give them different colors or save each rectangle into a different image file or put some text on them, etc.

The shapes should be white in a binary image, and the background should be black.

As shown, the color of the shapes in the output image is different from the color of shapes in the original image. The first argument of the findContours() function is the binary image, and the second argument is the contour retrieval method.

Читайте также:  Print script name python

We use the cv2.RETR_EXTERNAL because we only need the external contours. The third argument is the approximation method used to find the contours.

Hello! I am Ammar Ali, a programmer here to learn from experience, people, and docs, and create interesting and useful programming content. I mostly create content about Python, Matlab, and Microcontrollers like Arduino and PIC.

Related Article — OpenCV Image

Источник

OpenCV на python: поиск прямоугольников и эллипсов

Разобравшись с выделением контуров объектов на видео, перейдем к более сложной задаче — обнаружению прямоугольников и эллипсов. Более того, мы не только научимся находить их в кадре, но еще и сможем определять угол их наклона!

Хорошим примером использования подобных алгоритмов может стать ситуация, когда роботу нужно правильно ухватиться за предмет. Прямо как на картинке.

Робот манипулятор хватает предмет

Если смотреть на цилиндр сверху, то он превратится в прямоугольник. Зная его координаты в кадре и угол наклона можно рассчитать поворот схвата манипулятора, чтобы правильно ухватиться за предмет.

  1. Функция OpenCV для поиска прямоугольников minAreaRect
  2. Функция OpenCV для поиска эллипсов fitEllipse
  3. Отсечение лишних контуров по площади
  4. Вычисление угла поворота прямоугольника в OpenCV
  5. Определение угла поворота прямоугольника в видеопотоке

1. Функция OpenCV для поиска прямоугольников minAreaRect

В OpenCV имеется функция, которая пытается найти прямоугольник максимального размера, который может вписаться в заданный замкнутый контур. Надо заметить, что эта функция не определяет является ли контур прямоугольным, она пытается вписать в него прямоугольник оптимальным способом. Это важно!

контур — это контур, в который мы собираемся вписать прямоугольник (тип аргумента — Nx2 массив NumPy).

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

#!/usr/bin/env python import sys import numpy as np import cv2 as cv hsv_min = np.array((0, 54, 5), np.uint8) hsv_max = np.array((187, 255, 253), np.uint8) if __name__ == '__main__': fn = 'image2.jpg' # имя файла, который будем анализировать img = cv.imread(fn) hsv = cv.cvtColor( img, cv.COLOR_BGR2HSV ) # меняем цветовую модель с BGR на HSV thresh = cv.inRange( hsv, hsv_min, hsv_max ) # применяем цветовой фильтр _, contours0, hierarchy = cv.findContours( thresh.copy(), cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE) # перебираем все найденные контуры в цикле for cnt in contours0: rect = cv.minAreaRect(cnt) # пытаемся вписать прямоугольник box = cv.boxPoints(rect) # поиск четырех вершин прямоугольника box = np.int0(box) # округление координат cv.drawContours(img,[box],0,(255,0,0),2) # рисуем прямоугольник cv.imshow('contours', img) # вывод обработанного кадра в окно cv.waitKey() cv.destroyAllWindows()

Результат работы программы:

Читайте также:  Html файлы на смартфоне

OpenCV на python, поиск прямоугольников

Видно, что алгоритм попытался вписать прямоугольники во вложенные мусорные контуры на самих объектах. Далее мы разберемся как с этим бороться.

Теперь попробуем тоже самое, но с эллипсами.

2. Функция OpenCV для поиска эллипсов fitEllipse

Как и в случае minAreaRect, функция поиска эллипсов не сможет отличить на картинке объект с действительно эллиптическим контуром от квадрата. Она лишь пытается эллипс вписать в любой контур с количеством точек >=5.

контур — это контур, в который мы собираемся вписать прямоугольник (тип аргумента — Nx2 массив NumPy).

Слегка изменим предыдущую программу, убрав из неё minAreaRect и добавив fitEllipse.

#!/usr/bin/env python import sys import numpy as np import cv2 as cv hsv_min = np.array((0, 77, 17), np.uint8) hsv_max = np.array((208, 255, 255), np.uint8) if __name__ == '__main__': fn = 'donuts.jpg' img = cv.imread(fn) hsv = cv.cvtColor( img, cv.COLOR_BGR2HSV ) thresh = cv.inRange( hsv, hsv_min, hsv_max ) _, contours0, hierarchy = cv.findContours( thresh.copy(), cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE) for cnt in contours0: if len(cnt)>4: ellipse = cv.fitEllipse(cnt) cv.ellipse(img,ellipse,(0,0,255),2) cv.imshow('contours', img) cv.waitKey() cv.destroyAllWindows()

необходимо для того, чтобы отсечь контуры с контурами меньше 5 точек. Результат работы программы:

OpenCV на python, поиск эллипсов

Надо заметить, что эллипсы лучше пытаться вписать в округлые объекты, а прямоугольники в прямоугольные:) В противном случае, алгоритм может выдать неадекватные результаты.

3. Отсечение лишних контуров по площади

Следующий шаг — разберемся с паразитными микроконтурами, которые мы обнаружили на объектах. Избавиться от них можно, вычислив площадь занимаемую этими контурами, а затем просто отсечь контуры с маленькой площадью.

Внесем в нашу программу модификацию:

box = np.int0(box) # округление координат area = int(rect[1][0]*rect[1][1]) # вычисление площади if area > 500: cv.drawContours(img,[box],0,(255,0,0),2)

OpenCV на python, поиск прямоугольников

4. Вычисление угла поворота прямоугольника в OpenCV

Наконец, вычислим углы наклона всех прямоугольников относительно горизонта. Здесь нам не понадобятся специальные функции OpenCV, достаточно будет простой математики.

#!/usr/bin/env python import sys import numpy as np import cv2 as cv import math hsv_min = np.array((0, 54, 5), np.uint8) hsv_max = np.array((187, 255, 253), np.uint8) color_blue = (255,0,0) color_yellow = (0,255,255) if __name__ == '__main__': fn = 'image2.jpg' # имя файла, который будем анализировать img = cv.imread(fn) hsv = cv.cvtColor( img, cv.COLOR_BGR2HSV ) # меняем цветовую модель с BGR на HSV thresh = cv.inRange( hsv, hsv_min, hsv_max ) # применяем цветовой фильтр _, contours0, hierarchy = cv.findContours( thresh.copy(), cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE) # перебираем все найденные контуры в цикле for cnt in contours0: rect = cv.minAreaRect(cnt) # пытаемся вписать прямоугольник box = cv.boxPoints(rect) # поиск четырех вершин прямоугольника box = np.int0(box) # округление координат center = (int(rect[0][0]),int(rect[0][1])) area = int(rect[1][0]*rect[1][1]) # вычисление площади # вычисление координат двух векторов, являющихся сторонам прямоугольника edge1 = np.int0((box[1][0] - box[0][0],box[1][1] - box[0][1])) edge2 = np.int0((box[2][0] - box[1][0], box[2][1] - box[1][1])) # выясняем какой вектор больше usedEdge = edge1 if cv.norm(edge2) > cv.norm(edge1): usedEdge = edge2 reference = (1,0) # горизонтальный вектор, задающий горизонт # вычисляем угол между самой длинной стороной прямоугольника и горизонтом angle = 180.0/math.pi * math.acos((reference[0]*usedEdge[0] + reference[1]*usedEdge[1]) / (cv.norm(reference) *cv.norm(usedEdge))) if area > 500: cv.drawContours(img,[box],0,(255,0,0),2) # рисуем прямоугольник cv.circle(img, center, 5, color_yellow, 2) # рисуем маленький кружок в центре прямоугольника # выводим в кадр величину угла наклона cv.putText(img, "%d" % int(angle), (center[0]+20, center[1]-20), cv.FONT_HERSHEY_SIMPLEX, 1, color_yellow, 2) cv.imshow('contours', img) cv.waitKey() cv.destroyAllWindows()

Помним, что цветовые фильтры hsv_min и hsv_max нужно каждый раз настраивать под конкретный объект и освещение!

Читайте также:  Локальный ip адрес php

Запускаем программу, указав в ней в качестве исходного — изображение с макетными платами.

OpenCV на python, поиск прямоугольников и вычисление угла наклона

Ура! Работает. Ну и последний шаг — подключим видеопоток.

5. Определение угла поворота прямоугольника в видеопотоке

#!/usr/bin/env python import cv2 as cv import numpy as np import video import math if __name__ == '__main__': cv.namedWindow( "result" ) cap = video.create_capture(0) hsv_min = np.array((0, 0, 255), np.uint8) hsv_max = np.array((72, 51, 255), np.uint8) color_blue = (255,0,0) color_red = (0,0,128) while True: flag, img = cap.read() img = cv.flip(img,1) try: hsv = cv.cvtColor(img, cv.COLOR_BGR2HSV ) thresh = cv.inRange(hsv, hsv_min, hsv_max) _, contours0, hierarchy = cv.findContours( thresh.copy(), cv.RETR_EXTERNAL, cv.CHAIN_APPROX_NONE) for cnt in contours0: rect = cv.minAreaRect(cnt) box = cv.boxPoints(rect) box = np.int0(box) center = (int(rect[0][0]),int(rect[0][1])) area = int(rect[1][0]*rect[1][1]) edge1 = np.int0((box[1][0] - box[0][0],box[1][1] - box[0][1])) edge2 = np.int0((box[2][0] - box[1][0], box[2][1] - box[1][1])) usedEdge = edge1 if cv.norm(edge2) > cv.norm(edge1): usedEdge = edge2 reference = (1,0) # horizontal edge angle = 180.0/math.pi * math.acos((reference[0]*usedEdge[0] + reference[1]*usedEdge[1]) / (cv.norm(reference) *cv.norm(usedEdge))) if area > 500: cv.drawContours(img,[box],0,color_blue,2) cv.circle(img, center, 5, color_red, 2) cv.putText(img, "%d" % int(angle), (center[0]+20, center[1]-20), cv.FONT_HERSHEY_SIMPLEX, 1, color_red, 2) cv.imshow('result', img) except: cap.release() raise ch = cv.waitKey(5) if ch == 27: break cap.release() cv.destroyAllWindows()

Помним про правильную настройку фильтров! Если всё сделано правильно, получится примерно это:

Your browser does not support the video tag.
К размышлению

Итак, хорошая новость — мы умеем определять угол наклона прямоугольника. Плохая новость — мы не можем быть уверены, что в кадре именно прямоугольник! Та же ситуация с эллипсом. Попробуем разобраться с более продвинутыми методами детектирования геометрических объектов на следующих уроках!

Источник

Оцените статью