2021年亚太杯APMCM数学建模大赛
A题 图像边缘分析与应用
原题再现:
随着科学技术的发展,对各种工件和零部件测量精度的要求越来越高,对测量仪器的要求也越来越高。数字图像尺寸测量仪器等各种图像测量设备目前正逐渐取代传统的手动卡尺测量应用。一般来说,在相机校准后,根据校准图像的点矩阵或棋盘特征信息,对图像进行失真校正,计算出图像坐标空间与世界坐标空间之间的映射关系。
目标对象的边缘对图像识别和计算机分析非常有用。图像边缘是对图像的局部特征的不连续性的反映。该边缘可以勾勒出目标物体,并让观察者一眼就看清楚它。边缘包含丰富的内在信息(如方向、步长属性和形状等),这是在图像识别中提取图像特征的一个重要属性。图像边缘轮廓提取是边界分割中一个非常重要的处理过程,也是图像处理中的一个经典问题。轮廓提取和轮廓跟踪的目的都是获取图像的外部轮廓特征。在必要时应用某些方法来表示轮廓的特征,以准备图像形状分析,对执行特征描述、识别和理解等高级处理具有重要影响。
该轮廓可以被描述为一组有序的点,并且该轮廓的共同表达式是一个多边形。轮廓既可以关闭,也可以打开。图像上的闭合轮廓从头到尾都是连接的,开放的轮廓通常与图像边界相交。在图1中,有5条封闭的轮廓曲线。虽然sobel、canny等边缘检测算法可以根据图像灰度值的差值来检测图像边缘像素的边界,但它并不考虑一个整体的轮廓。在一个图像上,一个轮廓对应于一系列的像素点。该轮廓描述了一个连续的点序列,并且边缘像素点可以组装成一个轮廓曲线来描述图像的边缘信息。
子像素是在图像采集传感器的两个物理像素之间定义的虚拟像素。为了提高分辨率或图像质量,亚像素计算非常有用。图像亚像素边缘提取是一种比传统的像素边缘提取更精确的方法。子像素表示图像上每个像素点的坐标值不再是整数定位,而是浮点数位。如果使用亚像素技术将精度提高到0.1像素,则相当于图像系统分析分辨率的10倍。
对于以下三幅示意图,在图1中,我们提取了图像的对象边缘轮廓线,并将图像边缘轮廓分割为直线段、圆弧段、圆段等基本图形。在图2中,一个圆角矩形的边缘轮廓被划分为几个几何形状。在图3中,在灰度像素图像网格的背景上绘制了一条椭圆的亚像素轮廓曲线。
问题1:建立数学模型,分析1/10像素精度以上亚像素边缘提取方法和过程,提取附件1三个图像(Pic1_1、Pic1_2、Pic1_3)上对象主边缘部分的亚像素边缘轮廓边界,将边缘亚像素点数据转换为有序边缘轮廓曲线数据,需要考虑如何消除边缘毛边和阴影部分的干扰效应。请注意,Pic1_3图像是在相对复杂的光照条件下拍摄的,并且有更多的干扰信息。
a) 请在图像上绘制不同颜色提取的边缘轮廓,输出为彩色边缘轮廓图像,并保存为png图像格式,以便提交。文件名为pic1_1.png、pic1_2.png、pic1_3.png。
b) 输出附件1中EdgeContoursOutput.xls文件格式的边缘轮廓数据,并将Pic1_1和Pic1_2图像的数据分别输出到工作表对应的表1和表2中。输出数据包含总边轮廓数、图像坐标空间中的总边轮廓长度、每个轮廓曲线的点数和长度,以及每个轮廓点的X、Y坐标数据。
c) 本文应给出各图像上的总轮廓曲线计数以及各曲线上的点计数和长度数据。详见表1、表2、表3。
问题2:在拍摄测量的图像时,在与目标物体相同的水平高度处放置一个点矩阵校准板。校准板上的点的直径为1mm,两个点之间的中心距离为2mm。附件2包含三个以不同角度拍摄的校准板图像和一张产品图像(Pic2_4.bmp)。请建立数学模型,利用校准板图像信息对产品图像进行图像整正分析,并考虑如何尽可能准确地计算产品图像上边缘分割拟合曲线段的实际物理尺寸。请计算每个边缘轮廓的长度(mm),最后计算出边 线 总 长 度 (mm) 。 根 据 图 4 所 示 的 轮 廓 数 据 标 注 , 输 出 附 录 2 中 的EdgeContoursLengthOutput.xls等表格式文件的数据结果。
问 题 3 : 附 件 3 提 供 了 两 个 亚 像 素 轮 廓 边 缘 数 据 (EdgeContour1.xls 和EdgeContour2.xls),形状如图5所示。建立数学模型,分析边缘轮廓曲线数据的自动分割拟合成直线段、圆弧段(含圆)或椭圆弧段(含椭圆),讨论边缘轮廓自动分割拟合的模型方法或策略。蓝色曲线从蓝色数字1标签开始,沿箭头方向输出模型计算结果数据。绿色曲线从绿色数字1标签开始,沿箭头方向输出模型计算结果数据。请将分段曲线段的参数填写到表格中。提交了论文中的表7和表8(关于轮廓1和轮廓2的分割数据)。请注意,此表中的行的类型是根据实际类型进行填充的。
备注:
1. 扫角表示从起点到终点的扫描角度,角度系统;
2. 尺寸表示指定椭圆或椭圆弧的半径值;
3. 旋转角度表示指定的椭圆或椭圆弧、角度系统的旋转角度值;
4. 对于旋转角度的方向,从x轴正方向到y轴正方向的旋转方向为正方向,反之亦然,为负方向。
5. 所有图像坐标点均在图像坐标系下表示,即左上角为(0,0)原点,x轴正向向右,y轴正向向下。
整体求解过程概述(摘要)
随着技术的突飞猛进,对测量仪器的要求也越来越高。本文介绍了边缘图像分割以及Canny算法和亚像素图像。零件的实际长度是根据校准板像素与实际距离的关系来测量的。最后,利用Ramer算法对图像进行拟合,然后准确提取图像边缘轮廓的实际数据。
对于问题1,通过绘制子像素边缘轮廓,首先需要将边缘子像素数据转换为有序的边缘轮廓曲线数据,考虑如何消除边缘毛边和阴影部分的干涉效应。Pic1_1和Pic1_2两个图像以相同的方式处理,使用拉普拉斯算子锐化图像,平滑图像轮廓,然后对OTSU二值化和高斯滤波进行阈值化去噪,最后用Canny算法粗略分割。处理Pic1_3图像是在环境复杂的条件下拍摄的。采用PSO-OTSU算法减少图像的亮点,最后进行零件缺陷检测和轮廓修复,得到理想的轮廓检测二值化图像。然后进行亚像素边缘检测,判断图像是否已经达到0.1像素,最后通过Ramer算法对图像边缘轮廓进行分割。
对于问题2,在测量给定零件图片的真实长度时,请根据给定水平的校准版本进行测量。所提供的产品图像的真实长度是根据提供的三种不同角度的校准板图像测量的。对于图像预处理,图像预处理需要OTSU二值化分割、高斯滤波去噪、图像校正和Canny算法分割。零件的拉普拉斯算子的图像锐化给出了最终的分割零件分割图像。后期,校准板和零件的亚像素级图像分割需要提取标记点的轮廓边缘,提高中心距测量的精度,零件需要测量精度以获得零件每个区域的像素周长。最后,测量每个零件的真实长度。
对于问题 3,对附件中提供的两个亚像素轮廓边缘数据进行建模,分析边缘轮廓曲线数据以拟合直线段、弧段或椭圆弧段,通过 Halcon 找到边缘的分割,得到轮廓的直线、圆和椭圆根据亚像素坐标数据读取,最后得到轮廓的中心、起始位置和终止位置。首先,在纸上执行轮廓分割,然后执行轮廓拟合中使用的Ramer算法,并进行边缘轮廓数据提取。
模型假设:
1.假设在提取图像定位点时,与最多线相交的点是图像的唯一中心点;
2.假设校准板高度与零件拍摄高度一致。
问题分析:
对于问题 1
要绘制子像素边缘轮廓,首先提取边缘轮廓,然后将边缘子像素数据转换为有序边缘轮廓的曲线数据,同时考虑如何消除边缘边缘和阴影部分的干涉效应。Pic1_1和Pic1_2两张图像以相同的方式进行处理,使用拉普拉斯算子锐化图像,平滑图像轮廓,然后进行OTSU二值化阈值和高斯滤波去噪,最后使用Canny算法进行粗略分割。处理Pic1_3图像是在环境复杂的条件下拍摄的。采用PSO-OTSU算法降低图像的亮点,最终对零件缺陷进行检测和轮廓修复,得到理想的轮廓检测二值化图像。然后进行亚像素边缘检测,判断图像是否达到0像素,最后用Ramer算法对图像边缘轮廓进行分割。
对于问题 2
在测量给定组件图片的真实长度时,需要根据给定电平的校准版本进行测量。真实长度根据提供的三种不同角度的校准板图像进行测量。图像处理需要通过OTSU二值化分割、高斯滤波去噪、图像校正和Canny算法分割进行图像预处理。零件的拉普拉斯算子的图像锐化给出了最终的分割零件分割图像。后期,校准板和零件的亚像素级图像分割需要提取标记点的轮廓边缘,提高中心距测量的精度,零件需要测量精度以获得零件每个区域的像素周长。最后,测量每个零件的真实长度。
对于问题 3
通过附件中提供的两个子像素轮廓边缘数据,对边缘轮廓分割进行建模,分析边缘轮廓曲线数据以拟合直线段、弧段或椭圆弧段,通过 Halcon 找到 Edge,根据读取的子像素坐标数据获取直线、圆和椭圆轮廓,最后得到中心, 轮廓的起始位置和终止位置无处不在。首先,将Ramer算法用于边缘轮廓的轮廓拟合和数据提取。
模型的建立与求解整体论文缩略图
全部论文请见下方“ 只会建模 QQ名片” 点击QQ名片即可
程序代码:
部分程序如下:
import cv2
import numpy as np
img = cv2.imread('/home/yasin/coffe.jpg')
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
_, contours, hierarchy = cv2.findContours(img_gray, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
cv2.drawContours(img, contours, -1, (255, 0, 255), 1)
cv2.namedWindow('Result of drawContours', 0)
cv2.imshow('Result of drawContours', img)
cv2.waitKey()
cnt = 0
for i in range(len(contours)):
arclen = cv2.arcLength(contours[i], True)
epsilon = max(3, int(arclen * 0.02))
approx = cv2.approxPolyDP(contours[i], epsilon, False) # 轮廓的多边形拟合
area = cv2.contourArea(contours[i]) # 计算面积
rect = cv2.minAreaRect(contours[i])
box = np.int0(cv2.boxPoints(rect))
h = int(rect[1][0])
w = int(rect[1][1])
if min(h, w) == 0:
ration = 0
else:
ration = max(h,w) /min(h,w)
if ration < 10 and area > 20 and area < 4000 and approx.shape[0] > 3 :
cv2.polylines(img, [approx], True, (0, 255, 0), 1)
cv2.namedWindow('Result of filtered', 0)
cv2.imshow('Result of filtered', img)
cv2.waitKey()