opencv basics Aprendizagem de contorno de 52 imagens 05 aquisição de casco convexo-cv2.convexHull()

Aproximar polígonos é uma grande aproximação de contornos, mas às vezes queremos simplificá-la usando o casco convexo de um polígono.
Uma casca convexa é semelhante a um polígono de aproximação, exceto que é o polígono "convexo" mais externo de um objeto. Uma casca convexa refere-se a um polígono que contém completamente o contorno original e é composto apenas por pontos no contorno. Cada parte da casca convexa é convexa, ou seja, a linha reta que conecta quaisquer dois pontos na casca convexa está dentro da casca convexa. Em um casco convexo, o ângulo interno de quaisquer três pontos consecutivos é menor que 180°.

Por exemplo, na Figura 12-25, o polígono mais externo é o casco convexo do manipulador, e a parte entre a borda do manipulador e o casco convexo é chamada de defeito convexo (Defeito de Convexidade), que pode ser usado para lidar com reconhecimento de gestos e outras questões.

insira a descrição da imagem aqui

obter casco convexo

O OpenCV fornece 函数 cv2.convexHull()um casco convexo para obter contornos. A sintaxe desta função é:

hull = cv2.convexHull(points[, sentido horário[, returnPoints]] )

A cobertura do valor de retorno na fórmula é o ponto de canto da cobertura convexa.
Os parâmetros da fórmula são os seguintes:

  • Pontos: esboço.
  • sentido horário: valor booleano. Quando o valor for True, os cantos da casca convexa serão dispostos no sentido horário; quando o valor for False, os cantos da casca convexa serão dispostos no sentido anti-horário.
  • returnPoints: valor booleano. O valor padrão é True, a função retorna as coordenadas dos eixos x/y dos cantos da casca convexa; quando é False, a função retorna os índices dos cantos da casca convexa no contorno.

Exemplo: observe a utilização do parâmetro returnPoints na função cv2.convexHull()

código mostra como abaixo:

import cv2
o = cv2.imread('contours.bmp')
gray = cv2.cvtColor(o,cv2.COLOR_BGR2GRAY)
ret, binary = cv2.threshold(gray,127,255,cv2.THRESH_BINARY)
contours, hierarchy = cv2.findContours(binary,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
hull = cv2.convexHull(contours[0]) # 返回坐标值
print("returnPoints 为默认值 True 时返回值 hull 的值:\n",hull)
hull2 = cv2.convexHull(contours[0], returnPoints=False) # 返回索引值
print("returnPoints 为 False 时返回值 hull 的值:\n",hull2)

resultado da operação:

returnPoints 为默认值 True 时返回值 hull 的值:
 [[[195 270]]

 [[195 383]]

 [[ 79 383]]

 [[ 79 270]]]
returnPoints 为 False 时返回值 hull 的值:
 [[3]
 [2]
 [1]
 [0]]

Como pode ser visto nos resultados da execução do programa, o parâmetro opcional returnPoints da função cv2.convexHull():

  • Quando o valor padrão é True, a função retorna as coordenadas dos eixos x/y dos pontos de canto do casco convexo. Neste exemplo, os valores das coordenadas de 4 contornos são retornados.
  • Quando Falso, a função retorna os índices dos pontos dos cantos da casca convexa no contorno, neste caso são retornados 4 valores de índice do contorno.

Exemplo 2: Use a função cv2.convexHull() para obter a cobertura convexa de um contorno.

código mostra como abaixo:

import cv2
# --------------读取并绘制原始图像------------------
o = cv2.imread('hand.bmp')
cv2.imshow("original",o)
# --------------提取轮廓------------------
gray = cv2.cvtColor(o,cv2.COLOR_BGR2GRAY)
ret, binary = cv2.threshold(gray,127,255,cv2.THRESH_BINARY)
contours, hierarchy = cv2.findContours(binary,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE)
# --------------寻找凸包,得到凸包的角点------------------
hull = cv2.convexHull(contours[0])
# --------------绘制凸包------------------
cv2.polylines(o, [hull], True, (0, 255, 0), 2)
# --------------显示凸包------------------
cv2.imshow("result",o)
cv2.waitKey()
cv2.destroyAllWindows()

insira a descrição da imagem aqui

defeito convexo

A parte entre o casco convexo e o contorno é chamada de defeito convexo. cv2.convexityDefects()Obtenha defeitos convexos usando a função em OpenCV . Seu formato de sintaxe é o seguinte:

convexityDefects = cv2.convexityDefects( contour, convexhull )

O valor de retorno convexityDefects na fórmula é o conjunto de pontos de defeitos convexos. É um array, e cada linha contém os valores [ponto inicial, ponto final, ponto no contorno mais distante da casca convexa, distância aproximada do ponto mais distante até a casca convexa].

需要注意的是,返回结果中[起点,终点,轮廓上距离凸包最远的点, a distância aproximada do ponto mais distante ao casco convexo] Os três primeiros valores são os índices dos pontos do contorno, então você precisa encontrá-los nos pontos do contorno.
Os parâmetros da fórmula são os seguintes:

  • contorno é o contorno.
  • convexhull é o casco convexo.

Deve-se notar que ao calcular defeitos convexos com cv2.convexityDefects(), o casco convexo deve ser usado como parâmetro. Ao buscar o casco convexo, o valor do parâmetro returnPoints da função cv2.convexHull() utilizado deve ser False.
Para permitir que todos observem o ponto de defeito convexo definido de forma mais intuitiva, tentamos exibir o ponto de defeito convexo definido em uma imagem. O método de implementação é conectar o ponto inicial e o ponto final com uma linha e desenhar um círculo no ponto mais distante. Abaixo utilizamos um exemplo para demonstrar a operação acima.

Exemplo 2: Calcular defeitos convexos usando a função cv2.convexityDefects().

código mostra como abaixo:

import cv2
#----------------原图--------------------------
img = cv2.imread('hand.bmp')
cv2.imshow('original',img)
#----------------构造轮廓--------------------------
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
ret, binary = cv2.threshold(gray, 127, 255,0)
contours, hierarchy = cv2.findContours(binary,
 cv2.RETR_TREE,
cv2.CHAIN_APPROX_SIMPLE)
#----------------凸包--------------------------
cnt = contours[0]
hull = cv2.convexHull(cnt,returnPoints = False)
defects = cv2.convexityDefects(cnt,hull)
print("defects=\n",defects)
#----------------构造凸缺陷--------------------------
for i in range(defects.shape[0]):
 s,e,f,d = defects[i,0]
 start = tuple(cnt[s][0])
 end = tuple(cnt[e][0])
 far = tuple(cnt[f][0])
 cv2.line(img,start,end,[0,0,255],2)
 cv2.circle(img,far,5,[255,0,0],-1)
#----------------显示结果,释放图像--------------------------
cv2.imshow('result',img)
cv2.waitKey(0)
cv2.destroyAllWindows()

resultado da operação:

defects=
 [[[    0   102    51 21878]]

 [[  103   184   150 13876]]

 [[  185   233   220  4168]]

 [[  233   238   235   256]]

 [[  238   240   239   247]]

 [[  240   294   255  2715]]

 [[  294   302   295   281]]

 [[  302   304   303   217]]

 [[  305   311   306   114]]

 [[  311   385   342 13666]]

 [[  385   389   386   395]]

 [[  389   489   435 20327]]]

insira a descrição da imagem aqui

Determine se o contorno é convexo

No OpenCV, a função cv2.isContourConvex() pode ser usada para determinar se o contorno é convexo e seu formato de sintaxe é:

retval = cv2.isContourConvex(contorno)

Na fórmula:

  • A recuperação do valor de retorno é um valor booleano. Quando True, o contorno é convexo; caso contrário, não é.
  • O contorno do parâmetro é o contorno a ser julgado.

Exemplo: Use a função cv2.isContourConvex() para determinar se o contorno é convexo.

código mostra como abaixo:

import cv2
o = cv2.imread('hand.bmp')
cv2.imshow("original",o)
gray = cv2.cvtColor(o,cv2.COLOR_BGR2GRAY)
ret, binary = cv2.threshold(gray,127,255,cv2.THRESH_BINARY)
contours, hierarchy = cv2.findContours(binary,
 cv2.RETR_LIST,
cv2.CHAIN_APPROX_SIMPLE)
#--------------凸包----------------------
image1=o.copy()
hull = cv2.convexHull(contours[0])
cv2.polylines(image1, [hull], True, (0, 255, 0), 2)
print("使用函数 cv2.convexHull()构造的多边形是否是凸形的:",
cv2.isContourConvex(hull))
cv2.imshow("result1",image1)
#------------逼近多边形--------------------
image2=o.copy()
epsilon = 0.01*cv2.arcLength(contours[0],True)
approx = cv2.approxPolyDP(contours[0],epsilon,True)
image2=cv2.drawContours(image2,[approx],0,(0,0,255),2)
print("使用函数 cv2.approxPolyDP()构造的多边形是否是凸形的:",
 cv2.isContourConvex(approx))
cv2.imshow("result2",image2)
#------------释放窗口--------------------
cv2.waitKey()
cv2.destroyAllWindows()

resultado da operação:

使用函数 cv2.convexHull()构造的多边形是否是凸形的: True
使用函数 cv2.approxPolyDP()构造的多边形是否是凸形的: False

insira a descrição da imagem aqui

A partir dos resultados de execução acima, pode-se ver que:

  • Depois de usar a função cv2.contourContourConvex() para construir o casco convexo, use a função cv2.isContourConvex() para julgar o casco convexo desenhado.O valor de retorno é True, indicando que o contorno é convexo.
  • Após utilizar a função cv2.approxPolyDP() para construir o polígono aproximado, utilize a função cv2.isContourConvex() para julgar o polígono aproximado desenhado, e o valor de retorno é False, indicando que o contorno (polígono) não é convexo.

A imagem original do experimento:

insira a descrição da imagem aqui

Acho que você gosta

Origin blog.csdn.net/hai411741962/article/details/132192433
Recomendado
Clasificación