Контуры — это просто границы объектов на изображении. Их можно использовать для различных задач, таких как обнаружение объектов, сегментация изображений, анализ формы и многое другое. OpenCV предоставляет функции для поиска контуров внутри изображения и управления ими. Вот базовый пример работы с контурами в OpenCV:

import cv2
import numpy as np

# Read the input image
image = cv2.imread('input_image.jpg')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

# Apply thresholding to create a binary image
ret, threshold = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)

# Find contours in the binary image
contours, hierarchy = cv2.findContours(threshold, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

# Create a copy of the original image for drawing contours
contour_image = image.copy()

# Draw contours on the contour image
cv2.drawContours(contour_image, contours, -1, (0, 255, 0), 2)

# Display the contour image
cv2.imshow('Contours', contour_image)

cv2.waitKey(0)
cv2.destroyAllWindows()

В этом примере:

  1. Мы читаем входное изображение и преобразуем его в оттенки серого.
  2. Мы применяем пороговую обработку для создания бинарного изображения, в котором интересующие объекты белые, а фон черный.
  3. Мы используем функцию cv2.findContours() для поиска контуров в бинарном изображении. Функция возвращает список контуров и иерархию вложенных контуров (которая в этом простом примере не используется).
  4. Мы создаем копию исходного изображения для рисования контуров.
  5. Мы используем cv2.drawContours() для рисования обнаруженных контуров на скопированном изображении. Аргумент -1 указывает на рисование всех контуров, (0, 255, 0) задает цвет (зеленый), а 2 — толщину контурных линий.

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

Еще один фрагмент кода с дополнительными разъяснениями…


"""
# Image Contours helps in shape Detection, Analyzation and Recognition.
# contours is just like a curve which is made by continous data. and this depends on the color or its intensity.
# In Simple words, (it is simply a curve joining all continous points which is having same color or intensity).
# Accepts gray Scale image.
# findContour() manipulate original image, so copy it before proceeding.
# findContour() is like finding white object from black background. so better be change the image accordingly.
# Contour Features:-
# Moments, Contour Area, Contour Perimeter, Contour approximation , Convexhull, Checking convexity, Bounding Rectangle(Straight boundary Rectangle, Rotated Rectangle), Minimum enclosing circle, Fitting an Ellipse, Fitting a line, 
# Contour retrieval Mode
# RETR_LIST = it simply retrieves all the contours and store in the list.
# RETR_EXTERNAL = You can use this mode if you want to extract only the outer contours. It might be useful in some cases.
# RETR_CCOMP =This mode retrieves all the contours and arranges them to a 2-level hierarchy. ie external contours of the 
# object (ie its boundary) are placed in hierarchy-1. And the contours of holes inside object (if any) is placed in hierarchy-2
# RETR_TREE =  It retrieves all the contours and creates a full family hierarchy list.


import cv2
import numpy as np

img = cv2.imread("C:\\Users\\RANGER\\Desktop\\Z7.jpg")
img = cv2.resize(img,(600,600))
img1 = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
img1 = cv2.resize(img1,(600,600))

ret,thresh = cv2.threshold(img1,63,255,0)

# detecting contours after after thresholding image...
# cnts(coordinate),hier(hierarchy) = findcontour(img,contour_retrival_mode,method)
# this function return list containing coordinates of founded contours and ech contour is an array of x,y and heirarchy
cnts, hier = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)

print(cnts,len(cnts))

# draw Contours 
# drawcontour(img,cnts, id of contour, color, thickness) # here if we draw contour just pass -1
img = cv2.drawContours(img,cnts,-1,(25,100,15),4)
# as you can see in the ouput dialog, there are 61 contour in this image if you want to perform on some specific number of contours.
# then write the number at -1(number should be between 0 number of contours.)
# img = cv2.drawContours(img,cnts,36,(25,100,15),4)

#output 
cv2.imshow("Originals --",img)
cv2.imshow("GrayScale--",img1)
cv2.imshow("Threshold--",thresh)


cv2.waitKey(0)
cv2.destroyAllWindows()
"""


################################################
# Contour and its functions
# Moment - Moment detect the functionality of the objects.it also return you the center points of the objects 


import cv2
#import numpy as np

img = cv2.imread("C:\\Users\\RANGER\\Desktop\\Z7.jpg")
img = cv2.resize(img,(600,700))
img1 = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
ret,thresh = cv2.threshold(img1,120,255,cv2.THRESH_BINARY_INV)

# Findcontour(img,contour_retrival_mode,method)
cnts, hier= cv2.findContours(thresh,cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

print("Number of Contours==",cnts ,"\n total contour ==",len(cnts))
print("Heirarchy ",hier)

# loop over Contours(img, cnts, -1,(10,20,100),4)
for c in cnts:  # Loop to reach every contours for moment operation.
    #compute the center of the contour
    #an image moment is a certain particular weighted average(moment)
    M = cv2.moments(c)    # passing all contours one by one into moment function
    print("M==",M)
    cX = int(M["m10"] / M["m00"]) # formula for finding x_coordinates
    cY = int(M["m01"] / M["m00"]) # formula for finding y_coordinates
    
    # draw the contour and center of the shape on the image
    cv2.drawContours(img,[c],-1,(0,255,0),2) # drawing contours
    cv2.circle(img,(cX,cY),1,(255,255,255),2) # drawing circle just as shape 
    cv2.putText(img, "center",(cX - 20, cY -20),cv2.FONT_HERSHEY_SIMPLEX,0.5,(255,255,255),2) #getting center and print also on the object.
    # parameter (img,"text",font,fontsize, (color parameter (255,255,255), 2, cv.LINE_AA))

#output
cv2.imshow("Original ",img)
cv2.imshow("gray",img1) 
cv2.imshow("Thresh",thresh)

cv2.waitKey(0)
cv2.destroyAllWindows()

"""
# Contour and its functions
# Moment - Moment detect the functionality of the objects.it also return you the center points of the objects 
# Apprroximation

import cv2
import numpy as np

img = cv2.imread("C:\\Users\\RANGER\\Desktop\\Z7.jpg")
img = cv2.resize(img,(600,700))
img1 = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
ret,thresh = cv2.threshold(img1,120,255,cv2.THRESH_BINARY_INV)

# Findcontour(img,contour_retrival_mode,method)
cnts, hier= cv2.findContours(thresh,cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

print("Number of Contours==",cnts ,"\n total contour ==",len(cnts))
print("Heirarchy ",hier)
 
area1 = []
# loop over Contours(img, cnts, -1,(10,20,100),4)
for c in cnts:  # Loop to reach every contours for moment operation.
    #compute the center of the contour
    #an image moment is a certain particular weighted average(moment)
    M = cv2.moments(c)    # passing all contours one by one into moment function
    print("M==",M)
    # you can extract useful data like area, centroid etc. Centroid is given by the relations, Cx=M10/M00 and Cy=M01/M00.
    cX = int(M["m10"]/M["m00"]) # formula for finding x_coordinates
    cY = int(M["m01"]/M["m00"]) # formula for finding y_coordinates
    
    #Finding Area of contour
    area = cv2.contourArea(c)
    area1.append(area)
    
    #Contour approx - It is use to approx shape with less number of vertices
    epsilon = 0.1 * cv2.arcLength(c,True) # arc length take contour and return it as small size as it can.
    # Note: the more small size of contour, the more good result will come.
    # 0.1 is a random value. but it shouldn't be more than 1. 
    # arclength() returns the parameter of contour
    data = cv2.approxPolyDP(c,epsilon, True)
    # then passing epsilon to polygon shape dp. Because polygon has multiple sides.
    # passed contour with True value, which will pass the value to data. other wise it will not pass to store data in data variable.
    
    # Convexhull is used to provide proper contours convexity
    # in other word, whatever area detected by contour which will be bounded with the help of convexHull() is called convexHull.
    # whatever area covered by object with what shape, will be convexity..
    hull = cv2.convexHull(data)
    
    # we are just creating bounded rectangle which will cover the whole image..
    x,y,w,h = cv2.boundingRect(hull)
    img = cv2.rectangle(img,(x,y), (x+w,y+h),(125,10,20),5)
    
    # draw the contour and center of the shape on the image
    cv2.drawContours(img,[c],-1,(0,255,0),2) # drawing contours
    cv2.circle(img,(cX,cY),7,(255,255,255),-1) # drawing circle just as shape 
    cv2.putText(img, "center",(cX - 20, cY -20),cv2.FONT_HERSHEY_SIMPLEX,0.5,(255,255,255),2) #getting center and print also on the object.
    # parameter (img,"text",font,fontsize, (color parameter (255,255,255), 2, cv.LINE_AA))

#output
cv2.imshow("Original ",img)
cv2.imshow("gray",img1) 
cv2.imshow("Thresh",thresh)

cv2.waitKey(0)
cv2.destroyAllWindows()
"""

Что такое аппроксимация, выпуклая оболочка на самом деле?

Сначала просмотрите этот фрагмент кода. Он содержит четкое определение новых тем.

#Contours - 
###############################################################################################################
#Contours can be explained simply as a curve joining all the continuous points 
#(along the boundary), having same color or intensity. 

#The contours are a useful tool for shape analysis and object detection and recognition

#For better accuracy, use binary images and also apply edge detection before 
#findig countours.

#findCountour function manipulate original imge so copy it before proceeding.
#findContour is like finding white object from black background.
#so you must turn image in white and background is black.

#We have to find and draw contours as per the requirement

# Image Contours helps in shape Detection, Analyzation and Recognition.
# contours is just like a curve which is made by continous data. and this depends on the color or its intensity.
# In Simple words, (it is simply a curve joining all continous points which is having same color or intensity).
# Accepts gray Scale image.
# findContour() manipulate original image, so copy it before proceeding.
# findContour() is like finding white object from black background. so better be change the image accordingly.
# Contour Features:-
# Moments, Contour Area, Contour Perimeter, Contour approximation , Convexhull, Checking convexity, Bounding Rectangle(Straight boundary Rectangle, Rotated Rectangle), Minimum enclosing circle, Fitting an Ellipse, Fitting a line, 
# Contour retrieval Mode
# RETR_LIST = it simply retrieves all the contours and store in the list.
# RETR_EXTERNAL = You can use this mode if you want to extract only the outer contours. It might be useful in some cases.
# RETR_CCOMP =This mode retrieves all the contours and arranges them to a 2-level hierarchy. ie external contours of the 
# object (ie its boundary) are placed in hierarchy-1. And the contours of holes inside object (if any) is placed in hierarchy-2
# RETR_TREE =  It retrieves all the contours and creates a full family hierarchy list.
############################################################################################################################
"""
# Sample program to find contours..
import cv2
import numpy as np

img = cv2.imread("C:\\Users\\RANGER\\Desktop\\Z7.jpg")
img = cv2.resize(img,(600,700))
img1 = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

ret,thresh = cv2.threshold(img1,220,255,cv2.THRESH_BINARY_INV)

#findcontour(img,contour_retrival_mode,method)
# detecting contours after after thresholding image...
# cnts(coordinate),hier(hierarchy) = findcontour(img,contour_retrival_mode,method)
# this function return list containing coordinates of founded contours and ech contour is an array of x,y and heirarchy
cnts,hier = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
#Here cnts is a list of contours. ANd each contour is an array with x, y cordinate   
#hier variable called hierarchy and it contain image information.
print("Number of contour==",cnts,"\ntotal contour==",len(cnts))
print("Hierarchy==\n",hier)

# loop over the contours
for c in cnts:
    # compute the center of the contour
    #an image moment is a certain particular weighted average (moment) of the image pixels
    M = cv2.moments(c)
    print("M==",M)
    # These are nothing but the formula to find the x and y coordinate 
    # # you can extract useful data like area, centroid etc. Centroid is given by the relations, Cx=M10/M00 and Cy=M01/M00.
    cX = int(M["m10"] / M["m00"])
    cY = int(M["m01"] / M["m00"])
    
    
    # draw the contour and center of the shape on the image
    cv2.drawContours(img, [c], -1, (0, 255, 0), 2)
    cv2.circle(img, (cX, cY), 7, (255, 255, 255), -1)
    cv2.putText(img, "center", (cX - 20, cY - 20),cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255), 2)
    
cv2.imshow("original===",img)
cv2.imshow("gray==",img1)
cv2.imshow("thresh==",thresh)
cv2.waitKey(0)
cv2.destroyAllWindows()
"""
""" 
############################################################################################################################################
#-------------Contour Area , Approximation and Convex hull
# Program ---- 2
#Find countour area , aprroximation and convex hull
img = cv2.imread("C:\\Users\\RANGER\\Desktop\\Z7.jpg")
img = cv2.resize(img,(600,700))
img1 = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

ret,thresh = cv2.threshold(img1,220,255,cv2.THRESH_BINARY_INV)

#findcontour(img,contour_retrival_mode,method)
cnts,hier = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
#Here cnts is a list of contours. ANd each contour is an array with x, y cordinate   
#hier variable called hierarchy and it contain image information.
print("Number of contour==",cnts,"\ntotal contour==",len(cnts))
#print("Hierarchy==\n",hier)

area1 = []
# loop over the contours
for c in cnts:
    # compute the center of the contour
    #an image moment is a certain particular weighted average (moment) of the image pixels
    M = cv2.moments(c)
    #print("M==",M)
    cX = int(M["m10"] / M["m00"])
    cY = int(M["m01"] / M["m00"])
    #find area of contour
    area = cv2.contourArea(c)
    area1.append(area)
    
    if area<10000:
        #contour Approx -  it is use to approx shape with less number of vertices
        epsilon = 0.1*cv2.arcLength(c,True) #arc lenght take contour and return its perimeter
        data= cv2.approxPolyDP(c,epsilon,True)
        #Convexhull is used to provide proper contours convexity.
        
        hull = cv2.convexHull(data)
        
        x,y,w,h = cv2.boundingRect(hull)
        img = cv2.rectangle(img,(x,y),(x+w,y+h),(125,10,20),5)
 
    # draw the contour and center of the shape on the image
    cv2.drawContours(img, [c], -1, (50, 100, 50), 2)
    cv2.circle(img, (cX, cY), 7, (255, 255, 255), -1)
    cv2.putText(img, "center", (cX - 20, cY - 20),
                cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255), 2)
    
    
cv2.imshow("original===",img)
cv2.imshow("gray==",img1)
cv2.imshow("thresh==",thresh)
cv2.waitKey(0)
cv2.destroyAllWindows()
"""

####################################################################################################################################
# Program --- 3
# find contours in an image of hand show convexity
# Convexhull is nothing but the whole area where all contours exists. 

import cv2

img = cv2.imread("C:\\Users\\RANGER\\Desktop\\hand.jpg")
img = cv2.resize(img,(600,700))
img1 = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

# when performing threshold after that too we are not getting clear view and noiseless image. yes there are still some dot marks and noises.
# so we will clean it manually
blur = cv2.medianBlur(img1,5)
ret,thresh = cv2.threshold(blur,240,255,cv2.THRESH_BINARY_INV)

#findcontour (img,contour_retrieval_mode, method)
cnts, hier = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

# Draw the contours
#cv2.drawContours(img,cnts,-1,(50,50,150),2) # here -1 means draw all contours from image.

# convexHull...
for c in cnts:
    epsilon = 0.0001* cv2.arcLength(c,True) #
    data = cv2.approxPolyDP(c,epsilon,True)
    
    hull = cv2.convexHull(data)
    
    cv2.drawContours(img, [c], -1 ,(50,50,150),2)
    cv2.drawContours(img, [hull], -1 ,(0,255,0),2)

# Convexity Effect 
hull2 = cv2.convexHull(cnts[0],returnPoints = False) # hull2 will store the coordinates when returnpoints= False. 
# defect returns an array which contain value [start_point, end_point, far point, approximation points]
defect = cv2.convexityDefects(cnts[0], hull2)


for i in range(defect.shape[0]):
    s,e,f,d = defect[i,0]
    print(s,e,f,d)
    start = tuple(c[s][0])
    end = tuple(c[e][0])
    far = tuple(c[f][0])
    # cv2.line(img, start, end, [255,0,0],2)
    cv2.circle(img, far, 5,[0,0,255],-1)

# Extreme Points
#it means topmost, bottommost, rightmost, leftmost point of the object.

c_max = max(cnts, key=cv2.contourArea)

#determine the most extreme points along the contour
extLeft = tuple(c_max[c_max[:, :, 0].argmin()][0])
extRight = tuple(c_max[c_max[:, :, 0].argmin()][0])
extTop = tuple(c_max[c_max[:, :, 1].argmin()][0])
extButtom = tuple(c_max[c_max[:, :,1].argmin()][0])

# draw the ouline of the object then draw each of the extreme points, where the left most is red, right-most is green, top-most is blue, and buttom most is teal.

cv2.circle(img,extLeft,8,(255,0,255),-1)#pink
cv2.circle(img,extRight,8,(0,125,255),-1)#brown
cv2.circle(img,extTop,8,(255,10,0),-1)#blue
cv2.circle(img,extButtom,8,(19,152,152),-1)#green

cv2.imshow("Original==",img)
cv2.imshow("gray== ",img1)
cv2.imshow("Threshold= ",thresh) 
cv2.waitKey(0)

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

OpenCV предоставляет функцию cv2.convexHull(), которая вычисляет выпуклую оболочку набора точек или вершин контура.

Теперь посмотрите на этот простой пример контурной выпуклой оболочки…

import cv2
import numpy as np

# Read the input image
image = cv2.imread('input_image.jpg')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

# Apply thresholding to create a binary image
ret, threshold = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)

# Find contours in the binary image
contours, hierarchy = cv2.findContours(threshold, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

# Get the largest contour (you can choose a different one based on your needs)
largest_contour = max(contours, key=cv2.contourArea)

# Calculate the convex hull of the largest contour
convex_hull = cv2.convexHull(largest_contour)

# Create a copy of the original image for drawing the convex hull
convex_hull_image = image.copy()

# Draw the convex hull on the image
cv2.drawContours(convex_hull_image, [convex_hull], -1, (0, 255, 0), 2)

# Display the convex hull image
cv2.imshow('Convex Hull', convex_hull_image)

cv2.waitKey(0)
cv2.destroyAllWindows()

В этом примере:

  1. Мы читаем входное изображение и преобразуем его в оттенки серого.
  2. Мы применяем пороговую обработку для создания двоичного изображения.
  3. Находим контуры на бинарном изображении.
  4. Мы получаем самый большой контур, используя max() и cv2.contourArea().
  5. Мы вычисляем выпуклую оболочку наибольшего контура с помощью cv2.convexHull().
  6. Мы создаем копию исходного изображения, на которой будем рисовать выпуклую оболочку.
  7. Мы используем cv2.drawContours(), чтобы нарисовать выпуклую оболочку скопированного изображения.

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