Python + OpenCV : 已知多边形轮廓的点坐标,自动识别多边形顶点坐标的算法

最近做工程,根据提供的目标物体的坐标(比如说分割结果输出的目标像素坐标),标其中遇到了RT说述问题,OpenCV并没有提供现成的函数,并且网上关于这块几乎没有内容,所以在这里记录一下。先来啰嗦一下两个基础函数,熟悉可略过。

1.OpenCV提供了cv2.drawContours()函数可根据所提供的边界点绘制任何形状的轮廓。
eg:cv2.drawContours(image, [np.array(points, dtype=np.int32)], -1, (0, 0, 255), 2)
参数列表:它的第一个参数是原始图像,第二个参数是轮廓,一个坐标列表(一般为int32类型,否则会报错),第三个参数是轮廓的索引,接下来的参数是轮廓的颜色和厚度。
返回值:绘制轮廓后的原图(详见API)。

2.OpenCV函数提供了cv2.findContours()来寻找目标的边界
eg:cv2.findContours(binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
参数列表:它的第一个参数是输入图像(注意哦,二值图,即黑白的,并不是灰度图,所以读取的图像要先转成灰度的,再转成二值图),第二个参数是轮廓检索模式,第三个参数是轮廓近似方法。
返回值:这里OpenCV版本不同,返回值个数也不同,调用len()可以得到返回值的个数;当返回两个值,第一个为轮廓的点集,第二个是各层轮廓的索引(每一个轮廓都是一个Numpy数组,包含对象边界点(x,y)的坐标。)。当返回三个值,第一个是返回了你所处理的图像,第二个是我们要找的轮廓的点集,第三个是各轮廓的索引(详见API)。

寻找多边形的顶点坐标

第一步
为了准确,要使用二值化图像,需要进行阀值化处理。 在OpenCV中,阈值化操作通俗来讲,就在一个二值图像中查找轮廓,就像在黑色背景中寻找白色目标。但是查找轮廓的函数会修改原始图像。如果之后想继续使用原始图像,应该将原始图像储存到其他变量中,我在这里初始化了一张与原图同样大小的空白图像(image1 = np.zeros_like(image))。
第二步
先用cv2.convexHull()和cv2.approxPolyDP()简化点集,过滤掉部分点方便后续顶点识别,顶点识别算法的主要思想:求轮廓点集中每相邻的三个点形成的夹角的大小,当相邻三个点位于多边形的边上时,夹角趋于180,而顶点形成的夹角要小于180度,用一个二维数组记录相邻三点形成的夹角和三点中角点在源点集中的下标,最后对该数据排序,返回形成角度最小的角点,即为多边形的顶点。代码如下:

def bubble_sort_flag(list, axis):#根据数组的某一维排序
    length = len(list)
    for index in range(length):
        # 标志位
        flag = True
        for j in range(1, length - index):
            if axis == 0 and list[j - 1][0] > list[j][0]:
                list[j - 1][0], list[j][0] = list[j][0], list[j - 1][0]
                list[j - 1][1], list[j][1] = list[j][1], list[j - 1][1]
                flag = False
            if axis == 1 and list[j - 1][1] > list[j][1]:
                list[j - 1][0], list[j][0] = list[j][0], list[j - 1][0]
                list[j - 1][1], list[j][1] = list[j][1], list[j - 1][1]
                flag = False
        if flag:
            # 没有发生交换,直接返回list
            return list
    return list
'''atan2 方法返回一个 -pi 到 pi 之间的数值,表示点 (x, y) 对应的偏移角度。这是一个逆时针角度,以弧度为单位,正X轴和点 (x, y) 与原点连线 之间
因为atan2返回的是弧度值,也就是从-PI到PI,如下图所示,一个半圆是180度=弧度PI,所以1度 = PI/180。'''
def angle(v1, v2):
    dx1 = v1[2] - v1[0]
    dy1 = v1[3] - v1[1]
    dx2 = v2[2] - v2[0]
    dy2 = v2[3] - v2[1]
    angle1 = math.atan2(dy1, dx1)
    angle1 = int(angle1 * 180 / math.pi)
    angle2 = math.atan2(dy2, dx2)
    angle2 = int(angle2 * 180 / math.pi)
    if angle1 * angle2 >= 0:
        included_angle = abs(angle1 - angle2)
    else:
        included_angle = abs(angle1) + abs(angle2)
        if included_angle > 180:
            included_angle = 360 - included_angle
    return included_angle
hull = cv2.convexHull(max_contour)#求凸包,去掉曲线上的点
epsilon = 2#根据实际情况去设定
hull = cv2.approxPolyDP(hull1, epsilon, True)  
length = len(hull)
if(length > 4):
   ang = []
   for p in range(0, length):
      temp_1 = np.array([hull[(p + 1) % length][0], hull[(p + 1) % length][1], hull[p][0], hull[p][1]])
      temp_2 = np.array([hull[(p + 1) % length][0], hull[(p + 1) % length][1],hull[(p + 2) % length][0], hull[(p + 2) % length][1]])
      ang.append([angle(temp_1, temp_2), (p + 1) % length])
ang = np.array(ang)
ang = bubble_sort_flag(ang_1, 0)#根据数组的第一维排序
import numpy as np
np.set_printoptions(threshold=np.inf)
img=cv2.imread('synthesized_image_0.jpg')
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
                                    原文地址:opencv轮廓高级应用(轮廓匹配,几何直方图)作者:zhliangOpenCv轮廓高级应用(轮廓匹配,几何直方图)
最近再次用到了opencv轮廓,在这里结合作者冰山一角的博客(http://www.cnblogs.com/slysky/)以及自己的体会在此稍加说明。其程序主要参见冰山一角的Blog,遗憾的是代码是OpenCV1.0写的,等有时间再用2.4.2改写一篇。
2.minAreaRect找到最小外接矩形;
3.得到最小外接矩形的中心坐标作为轮廓的中心坐标;
cv::threshold(Imsrc, Imdest, 200, 255, cv::/*THRESH_BINARY*/THRESH_BINARY_INV);//THRESH_BINARY_INV不检测图片画布轮廓
cv::findContours(Imdest, contoursDest, hierarchy, cv
with open("1.mks", "r") as f:  # 打开文件
    data_list = f.readlines()[1:]  # 读取文件
    for val in data_list:
        vals = val.split(" ")
        dat...
read_image (Image, 'D:/Halcon-WorkSpaces/Test/Image/test12.png')
points_foerstner (Image, 1, 2, 3, 200, 0.1, 'gauss', 'false', \
RowJunctions, ColumnJunctio...
                                    使用OpenCV函数cvpointPolygonTest执行轮廓测试该函数确定是在轮廓线内、外,还是位于边缘(或与顶点重合)。它会相应地返回正(内部)、负(外部)或零(边缘)值。当measureDist=false时,返回值分别是+1,-1和0。否则,返回值是和最近的轮廓边缘之间的符号距离。...
使用 cv2.cvtColor() 函数将图像转换为灰度图像。
使用 cv2.threshold() 函数对图像进行二值化处理。
使用 cv2.findContours() 函数查找图像中的轮廓。
示例代码如下:
import cv2
# 读取图像
img = cv2.i...
                                    该软件使用python写的,可以提取像素坐标还有也能获取像素的像素数据(rgb565),可以单坐标也可以按键坐标,甚至可以使用简单的左右键配合使用,自动复制到粘贴板。
能学到py gui的基本使用,打开图片、读取像素、画布与滚动条联动、鼠标事件等等
CSDN:曹谋仁
文章目录检测前预处理----边缘检测二值图findContours函数----检测轮廓contourArea、arcLength函数----面积、周长contourArea函数----轮廓面积arcLength函数----轮廓长度approxPolyDP函数----曲线折线化drawContours函数----绘制轮廓
检测前预处理----边缘检测二值图
所谓形状/轮廓的检测就是把待检测图像中的边缘轮廓组成的图形识别出来,并检测出.