亚像素以及实现原理、方法
一、什么是亚像素Sub-Pixel普通图像坐标是整数像素 (x,y)(120,85)灰度255 | █████200 | █150 | █100 | █50 |█----------------1 2 3 4 5像素但真实物体边缘不一定刚好落在像素中心如边缘真实位置可能在2.35 像素。亚像素定位允许(x,y)(120.37,84.92)也就是浮点坐标。本质利用灰度变化模型对离散像素进行连续函数拟合。具体方法如下二次曲线拟合灰度重心最小二乘相位相关插值计算真实位置二、亚像素实现方法方法原理应用灰度重心intensity centroid激光点曲线拟合parabola / Gaussian边缘插值bilinear / bicubic角点梯度法gradient peak边缘最小二乘fitting edgeHALCON相位法phase correlation图像配准三、经典亚像素算法1 二次曲线拟合最经典假设局部响应是一个二次函数2 灰度重心法适用于激光条纹。举例计算假设一个3×3光斑y\x012010201013080402203010计算总灰度102010 308040 203010 250计算X方向的灰度0*(103020) 0 1*(208030) 130 2*(104010) 120 250计算Y方向的灰度0*(102010) 0 1*(308040) 150 2*(203010) 120结果优点算法简单精度高计算快适合激光线缺点对噪声敏感对背景敏感通常会先阈值再计算重心3 梯度亚像素定位一维梯度定位pixel-1 pixel pixel1G1 G2 G3核心思想在梯度方向上寻找梯度最大值的位置再通过曲线拟合得到亚像素位置。位置梯度x-130x50x140二维梯度定位4、灰度最小二乘优化5、OpenCV 相位相关亚像素配准功能OpenCV 函数场景输出角点cv::cornerSubPix()Harris、Shi-Tomasi浮点坐标(x,y)模板匹配cv::phaseCorrelate()平移估计浮点位移(Δx, Δy)边缘/线自定义 插值梯度/线检测亚像素中心(x,y)寻找亚像素角点cornerSubPix 函数void cornerSubPix(InputArray image, InputOutputArray corners, Size winSize, Size zeroZone, TermCriteria criteria); image输入图像即源图像。 corners提供输入角点的初始坐标和精确的输出坐标。 winSize搜索窗口的一半尺寸。若 winSize Size(5,5)那就表示用5*21×5*21 11×11 大小的搜索窗口。 zeroZone死区的一半尺寸。真正搜索区域为 [zeroZone*21 , winSize*21]。值为-1-1表示没有死区。 criteria求角点的迭代过程的终止条件。要么是迭代数大于某个设定值要么是精度达到某个设定值甚至可以是它们的组合。https://www.cnblogs.com/ybqjymy/p/15936311.html#includeopencv.hpp #includeiostream #includestring #includevector using namespace std; using namespace cv; Mat src, cornerImg, grayImg; int mxCorners 10; RNG rngs { 12345 }; void Change(int, void*) { //计算整数角点 vectorPointcorners1; vectorPoint2fcorners2; //https://www.cnblogs.com/bjxqmy/p/12459005.html goodFeaturesToTrack(grayImg, corners1, mxCorners, 0.01, 10, Mat(), 3, false, 0.04); goodFeaturesToTrack(grayImg, corners2, mxCorners, 0.01, 10, Mat(), 3, false, 0.04); //计算精确角点 TermCriteria criteria TermCriteria(TermCriteria::EPS TermCriteria::MAX_ITER, 40, 0.001); cornerSubPix(grayImg, corners2, Size(5, 5), Size(-1, -1), criteria); Mat dst src.clone(); for (int i 0; i corners1.size(); i) { cout [ corners1[i].x , corners1[i].y ] endl; cout [ corners2[i].x , corners2[i].y ] endl endl; Scalar colors Scalar(rngs.uniform(0, 255), rngs.uniform(0, 255), rngs.uniform(0, 255)); circle(dst, corners2[i], 5, colors, -1); } imshow(dst, dst); } int main() { src imread(C:\\Users\\admin\\Desktop\\wafer\\abc.png); imshow(src, src); //转换为灰度图像 cvtColor(src, grayImg, COLOR_BGR2GRAY); namedWindow(dst); createTrackbar(maxCorners, dst, mxCorners, 100, Change); Change(0, 0); waitKey(0); }四、工业视觉亚像素精度算法精度灰度重心0.02 pixelCanny 亚像素0.05 pixel相位相关0.01 pixel角点优化0.03 pixel1、HALCON 如何做亚像素edges_sub_pix内部步骤1 高斯滤波2 Sobel 计算梯度3 非极大值抑制4 梯度方向插值5 亚像素定位2、为什么梯度法可以达到亚像素因为边缘位置 梯度最大位置而梯度曲线是连续函数所以通过二次拟合可以找到真实最大值。五、Halcon测试案例1*读取图片 read_image (Image, C:/Users/admin/Desktop/a.png) * 关闭窗口 dev_close_window () get_image_size (Image, Width, Height) dev_open_window (0, 0, Width, Height, black, WindowHandle) * * Segment a region containing the edges *基于全局阈值的图像快速阈值化 fast_threshold (Image, Region, 0, 120, 7) *获取一个边界区域 boundary (Region, RegionBorder, inner) *用圆形结构元素扩张一个区域。 dilation_circle (RegionBorder, RegionDilation, 3.5) *获得特定区域Region位置的图像 reduce_domain (Image, RegionDilation, ImageReduced) * * In the subdomain of the image containing the edges, * extract subpixel precise edges. *提取亚像素精密边缘轮廓 edges_sub_pix (ImageReduced, Edges, canny, 2, 20, 60) *将一个XLD轮廓分割为直线段、圆圆弧)、椭圆弧 segment_contours_xld (Edges, ContoursSplit, lines_circles, 5, 4, 3) * dev_display (Edges) *计算个数 count_obj (ContoursSplit, Number) dev_display (Image) *定义region填充模式 dev_set_draw (margin) dev_set_color (white) dev_update_window (off) for I : 1 to Number by 1 *选择一个元素 select_obj (ContoursSplit, ObjectSelected, I) *返回XLD轮廓的全局属性值 get_contour_global_attrib_xld (ObjectSelected, cont_approx, Attrib) * Fit a circle to the line segment that are arcs of a circle if (Attrib 0) *用圆近似XLD轮廓 fit_circle_contour_xld (ObjectSelected, ahuber, -1, 2, 0, 3, 2, Row, Column, Radius, StartPhi, EndPhi, PointOrder) *创建对应于圆或圆弧的XLD轮廓 gen_circle_contour_xld (ContCircle, Row, Column, Radius, 0, rad(360), positive, 1.0) endif endfor dev_set_colored (12) dev_set_line_width (3) dev_display (ContoursSplit) *将整个窗口的图片存储为Png图片 *dump_window_image (Image1, WindowHandle) *write_image(Image1 , png , 0 , 1.png )https://zhuanlan.zhihu.com/p/437990262案例2* * This example shows how subpixel precise edges can be * extracted from an image. dev_close_window () read_image (Image, fabrik) dev_open_window_fit_image (Image, 0, 0, -1, -1, WindowHandle) * The default parameter were adapted to find more * connected edges in the image. edges_sub_pix (Image, Edges, canny, 2, 12, 22) dev_set_part (0, 0, 511, 511) dev_display (Image) dev_set_colored (6) dev_display (Edges) disp_continue_message (WindowHandle, black, true) stop () * Zoom into the image to enable detailed edge inspection dev_set_part (160, 250, 210, 300) dev_display (Image) dev_display (Edges)
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2414968.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!