【python】OpenCV—Point Polygon Test

在这里插入图片描述

1、完整代码

from __future__ import print_function
from __future__ import division
import cv2 as cv
import numpy as np
# Create an image
r = 100
src = np.zeros((4*r, 4*r), dtype=np.uint8)
# 创建六边形的6个顶点
vert = [None]*6
vert[0] = (3*r//2, int(1.34*r))
vert[1] = (1*r, 2*r)
vert[2] = (3*r//2, int(2.866*r))
vert[3] = (5*r//2, int(2.866*r))
vert[4] = (3*r, 2*r)
vert[5] = (5*r//2, int(1.34*r))
# 根据六个顶点画6边形
for i in range(6):
    cv.line(src, vert[i],  vert[(i+1)%6], ( 255 ), 3)
# 获取六边形的轮廓
contours, _ = cv.findContours(src, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)
# 计算图上点到六边形的距离(带符号)
raw_dist = np.empty(src.shape, dtype=np.float32)
for i in range(src.shape[0]):
    for j in range(src.shape[1]):
        raw_dist[i,j] = cv.pointPolygonTest(contours[0], (j,i), True)
# 查找带符号的最大最小值
minVal, maxVal, _, maxDistPt = cv.minMaxLoc(raw_dist)
minVal = abs(minVal)
maxVal = abs(maxVal)
# 用图形表示距离
drawing = np.zeros((src.shape[0], src.shape[1], 3), dtype=np.uint8)
for i in range(src.shape[0]):
    for j in range(src.shape[1]):
        if raw_dist[i,j] < 0:
            drawing[i,j,0] = 255 - abs(raw_dist[i,j]) * 255 / minVal
        elif raw_dist[i,j] > 0:
            drawing[i,j,2] = 255 - raw_dist[i,j] * 255 / maxVal
        else:
            drawing[i,j,0] = 255
            drawing[i,j,1] = 255
            drawing[i,j,2] = 255
cv.circle(drawing,maxDistPt, int(maxVal),(255,255,255), 1, cv.LINE_8, 0)
cv.imshow('Source', src)
cv.imshow('Distance and inscribed circle', drawing)
cv.waitKey()

在这里插入图片描述
在这里插入图片描述

带符号的最大值,为六边形的中心,到六边形轮廓的距离最远

以此点位中心,画了个圆

六边形外的点,蓝色随着距离变大递减

六边形内的点,红色随着距离变大递减

六边形上的点,白色

2、涉及到的库

cv2.pointPolygonTest

用于判断一个点是否位于一个多边形内部、外部还是边上。这个函数在图像处理、计算机视觉和形状分析等领域中非常有用。以下是关于 cv2.pointPolygonTest() 函数的详细解析:

函数定义

cv2.pointPolygonTest(contour, pt, measureDist=False)
  • contour:输入的多边形轮廓,通常是一个由点构成的数组(numpy数组),这些点定义了多边形的边界。这些点可以通过如 cv2.findContours 等函数从图像中提取。
  • pt:需要检测的点,通常是一个包含 x 和 y 坐标的元组或 numpy.ndarray。
  • measureDist:一个布尔值参数,指定是否计算点到多边形边界的最短距离。
    1)如果为 True,则函数返回点到边界的带符号距离。当点在多边形内部时,距离为正;当点在多边形外部时,距离为负;当点在多边形边上时,距离为0。距离的绝对值表示点到多边形边界的实际最短距离。
    2)如果为 False(默认值),则函数返回一个整数,表示点相对于多边形的位置。返回值为 -1 表示点在多边形外部,0 表示点在多边形边上,+1 表示点在多边形内部。

使用场景

  • 形状分析:通过检测点是否在多边形内部,可以分析形状的属性和特征。
  • 物体检测:在图像处理中,可以检测物体边界框内的点是否在多边形内部,从而判断物体是否被完全包含在多边形内。
  • 图像分割:在图像分割任务中,可以使用该函数来判断像素点是否属于某个特定的区域或对象。

示例代码

import cv2  
import numpy as np  
  
# 定义一个多边形的顶点  
pts = np.array([[0, 0], [100, 0], [100, 100], [0, 100]], np.int32)  
pts = pts.reshape((-1, 1, 2))  # 将点集转换为 (n, 1, 2) 的形状  
  
# 待检测的点  
pt_inside = (50, 50)  # 多边形内部的一个点  
pt_on_edge = (100, 0)  # 多边形边上的一个点  
pt_outside = (150, 50)  # 多边形外部的一个点  
  
# 调用 pointPolygonTest  
dist_inside = cv2.pointPolygonTest(pts, pt_inside, measureDist=True)  
dist_on_edge = cv2.pointPolygonTest(pts, pt_on_edge, measureDist=True)  
dist_outside = cv2.pointPolygonTest(pts, pt_outside, measureDist=True)  
  
position_inside = cv2.pointPolygonTest(pts, pt_inside, measureDist=False)  
position_on_edge = cv2.pointPolygonTest(pts, pt_on_edge, measureDist=False)  
position_outside = cv2.pointPolygonTest(pts, pt_outside, measureDist=False)  
  
print(f"Inside distance: {dist_inside}")  
print(f"On edge distance: {dist_on_edge}")  
print(f"Outside distance: {dist_outside}")  
  
print(f"Inside position: {position_inside}")  
print(f"On edge position: {position_on_edge}")  
print(f"Outside position: {position_outside}")

output

Inside distance: 50.0
On edge distance: -0.0
Outside distance: -50.0
Inside position: 1.0
On edge position: 0.0
Outside position: -1.0

注意事项

  • 确保传入的轮廓(contour)是正确的,即它应该是一个由点构成的数组,这些点定义了多边形的边界。

  • 当 measureDist 为 True 时,返回的距离值是带符号的,正值表示点在多边形内部,负值表示在多边形外部,绝对值表示最短距离。

  • cv2.pointPolygonTest() 函数不会直接修改输入的图像或轮廓,它只是返回一个表示点位置的数值或距离。

cv2.minMaxLoc

用于寻找一维数值数组(例如,灰度图像的某一行或列)中的全局最小值和最大值,以及它们的位置。这个函数对于图像处理中的阈值设置、特征检测等场景非常有用。

cv2.minMaxLoc(src, mask=None)
  • src:输入的单通道数值数组。这可以是一个灰度图像,或者图像的某个部分(如一行或一列)。

  • mask:可选的与 src 同样大小和类型的操作掩码。如果提供了掩码,则函数仅在没有被掩码标记为忽略的元素中查找最小值和最大值。掩码中的非零值表示对应位置的元素需要考虑在内。

返回值

函数返回一个包含四个元素的元组 (minVal, maxVal, minLoc, maxLoc):

  • minVal:找到的最小值。
  • maxVal:找到的最大值。
  • minLoc:最小值的坐标(以元组形式给出,如 (x, y))。注意,对于一维数组(如图像的单个行或列),坐标将是 (col, 0),因为 y 坐标在这种情况下没有意义。
  • maxLoc:最大值的坐标(同样以元组形式给出)。

使用示例

import cv2  
import numpy as np  
  
# 加载图像(转换为灰度,如果它还不是)  
img = cv2.imread('path_to_image.jpg', cv2.IMREAD_GRAYSCALE)  
  
# 查找最小值和最大值以及它们的位置  
minVal, maxVal, minLoc, maxLoc = cv2.minMaxLoc(img)  
  
print(f"Minimum value: {minVal}, at location: {minLoc}")  
print(f"Maximum value: {maxVal}, at location: {maxLoc}")

如果你只对图像的某一行或列感兴趣,你可以先通过索引该行或列来创建一个一维数组,然后再调用 cv2.minMaxLoc。

注意:对于二维图像(如灰度图像),返回的坐标 (x, y) 是以图像的左上角为原点((0, 0))的坐标系统。但是,对于一维数组(如通过索引得到的行或列),y 坐标总是 0,因为此时我们实际上是在处理一维数据。

  • 6
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值