机器视觉_实验2.doc
如有侵权,请联系网站删除,仅供学习与交流机器视觉_实验2【精品文档】第 9 页实验二 多边形边长测量一、实验目的1 掌握哈夫变换方法检测直线的基本原理和步骤。2 复习VB/VC/Matlab的基本概念、基本语法和编程方法,并熟练使用VB/VC/Matlab编写遗传算法程序。二、实验设备微机三、 实验原理距离测量基本步骤:1)对定位距离的两条直线进行识别和拟合。(关键步骤)2)得到直线方程后,根据数学方法计算两线间的距离。两种经典的直线拟合(检测)算法:最小二乘法、哈夫(霍夫)变换法直线函数:y=ax+b,a、b是待定常数。Hough变换Hough,1962是一种利用图像全局特征将特定形状的边缘连接起来,形成连续平滑边缘的一种方法。 它通过将源图像上的点映射到用于累加的参数空间,实现对已知解析式曲线的识别。 由于Hough变换利用了图像全局特性,所以受噪声和边界间断的影响较小,比较鲁棒(Robust)。 Hough变换常用来对图像中的直线和圆进行识别。点-线对偶性:图像空间XY中共线的点,对应在参数空间PQ中相交的线。参数空间PQ中相交于一点的所有直线,在图像空间XY里都有共线的点与之对应。结论:在PQ平面上相交直线最多的点,对应在XY平面上的直线就是解。假设:1)图像上的直线是一个容器;2)直线上的点(图像中的特定像素)是放在容器中的棋子。由于图像上任一像素可以同时属于多根直线,即可看成每个棋子(像素)可以同时放在多个容器中(直线)。Hough变换的基本思想:依次检查图像上的每个棋子(特定像素)。对每个棋子,找到所有包含它的容器(直线),并为每个容器的计数器加1。遍历结束后,统计每个容器所包含的棋子数量。当图像上某个直线包含的特定像素足够多时,就可以认为直线存在。具体步骤:将rq空间量化,得到二维矩阵Mrq;根据极坐标表示法,r是直线到原点的距离。设图像的对角线长度为n,固定左上角为原点,则r的取值范围为0, n。令q以1度为增量,则q的取值范围为0, 359。此时,M是一个n行360列的二维矩阵。矩阵中任一元素Mrq所存储的值就是图像中由参数(r,q)决定的直线上所拥有的像素数。初始化时,矩阵M置为0。遍历图像,对像素(xi, yi) ,将q的所有量化值和像素坐标(xi, yi),依次代入直线的极坐标方程,计算r的值,根据当前r、q,将对应的累加器加1,即:Mrq=Mrq+1。分析Mrq,如果Mrq³T,就认为存在一条有意义的线段,(r,q)是该线段的拟合参数。T是一个非负整数,由图像中景物的先验知识决定,与图像大小有关。由(r,q)和(xi, yi)共同确定图像中的线段,并连接断裂部分。四、预习要求1 查阅资料,理解并掌握哈夫变换方法检测直线的基本原理与步骤。2 复习VB/VC/Matlab的基本概念、基本语法和编程方法。五、实验内容及步骤1 上机编写程序,以“六边形.bmp”为实验对象,利用哈夫变换方法检测出六边形各边边长。程序代码:#include "stdafx.h"#include "opencv2/highgui/highgui.hpp"#include "opencv2/imgproc/imgproc.hpp"#include <iostream>#include <stdio.h>using namespace cv;using namespace std;Mat src, edges;Mat src_gray;Mat standard_hough, probabilistic_hough;/标准霍夫变换,概率的霍夫变换int min_threshold = 10;/最小阈值为10int max_trackbar = 200;/最大的跟踪条为200char*standard_name = "Standard Hough Lines Demo"char*probabilistic_name = "Probabilistic Hough Lines Demo"int s_trackbar = max_trackbar;int p_trackbar = max_trackbar;void help();void Standard_Hough(int, void*);void Probabilistic_Hough(int, void*);int main()src = imread("六边形.bmp", 1);if (src.empty()help();return -1;cvtColor(src, src_gray, CV_RGB2GRAY);Canny(src_gray, edges, 50, 200, 3);namedWindow(standard_name, CV_WINDOW_AUTOSIZE);createTrackbar("Thresh", standard_name, &s_trackbar, max_trackbar, Standard_Hough);namedWindow(probabilistic_name, CV_WINDOW_AUTOSIZE);createTrackbar("Thresh", probabilistic_name, &p_trackbar, max_trackbar, Probabilistic_Hough);/初始化Standard_Hough(0, 0);Probabilistic_Hough(0, 0);waitKey(0);return 0;void help()printf("t Hough Transform to detect lines n");printf("t-n");printf("Usage:./HoughLines_Demo<image_name>n");void Standard_Hough(int, void*)vector<Vec2f>s_lines;cvtColor(edges, standard_hough, CV_GRAY2BGR);/用标准霍夫变换HoughLines(edges, s_lines, 1, CV_PI / 180, min_threshold + s_trackbar, 0, 0);/显示结果for (int i = 0; i < s_lines.size(); i+)float r = s_linesi0, t = s_linesi1;double cos_t = cos(t), sin_t = sin(t);double x0 = r*cos_t, y0 = r*sin_t;double alpha = 1000;Point pt1(cvRound(x0 + alpha*(-sin_t), cvRound(y0 + alpha*cos_t);Point pt2(cvRound(x0 - alpha*(-sin_t), cvRound(y0 - alpha*cos_t);line(standard_hough, pt1, pt2, Scalar(255, 0, 0), 1, CV_AA);imshow(standard_name, standard_hough);imwrite("六边形.bmp", standard_hough);void Probabilistic_Hough(int, void*)vector<Vec4i>p_lines;cvtColor(edges, probabilistic_hough, CV_GRAY2BGR);/用概率霍夫变换HoughLinesP(edges, p_lines, 1, CV_PI / 180, min_threshold + p_trackbar, 30, 10);/显示结果for (size_t i = 0; i < p_lines.size(); i+)Vec4i l = p_linesi;line(probabilistic_hough, Point(l0, l1), Point(l2, l3), Scalar(255, 0, 0), 1, CV_AA);imshow(probabilistic_name, probabilistic_hough);imwrite("六边形.bmp", probabilistic_hough);2 利用实验一的Harris角点检测程序,检测“六边形.bmp”中六边形的各边边长。源程序:#include "stdafx.h"#include "opencv2/highgui/highgui.hpp"#include "opencv2/imgproc/imgproc.hpp"#include "opencv2corecore.hpp"#include "opencv2legacylegacy.hpp"#include "opencv2nonfreenonfree.hpp"#include "opencv2highguihighgui.hpp"#include "opencv2calib3dcalib3d.hpp"#include <vector>#include <iostream>#include <stdio.h>using namespace cv;using namespace std;Mat src, src_gray, dst_norm_scaled, src_copy;int thresh = 0;int max_thresh = 100;int maxCorners = 0;int maxTrackbar = 50;/最大的跟踪条为50char*source_window = "Source image"char*corners_window = "Corners detected"void cornerHarris_demo(int, void*);int main()src= imread("六边形.bmp", 1);cvtColor(src, src_gray, CV_BGR2GRAY);/建立一个窗口和跟踪条namedWindow(source_window, CV_WINDOW_AUTOSIZE);createTrackbar("Harris", source_window, &thresh, max_thresh, cornerHarris_demo);createTrackbar("ShiTomasi", source_window, &maxCorners, maxTrackbar, cornerHarris_demo);namedWindow(corners_window, CV_WINDOW_AUTOSIZE);namedWindow(source_window, CV_WINDOW_AUTOSIZE);cornerHarris_demo(0, 0);waitKey(0);return(0);void cornerHarris_demo(int, void*)src.copyTo(src_copy);Mat dst, dst_norm;dst= Mat:zeros(src.size(), CV_32FC1);int blockSize= 2;int apertureSize= 3;double k= 0.04;cornerHarris(src_gray, dst, blockSize, apertureSize, k, BORDER_DEFAULT);normalize(dst, dst_norm, 0, 255, NORM_MINMAX, CV_32FC1, Mat();convertScaleAbs(dst_norm, dst_norm_scaled);for (int j = 0; j < dst_norm.rows; j+)for (int i = 0; i < dst_norm.cols; i+)if (int)dst_norm.at<float>(j, i)>thresh + 60)circle(dst_norm_scaled, Point(i, j), 6, Scalar(0), -1, 8, 0);circle(src_copy, Point(i, j), 5, Scalar(255, 0, 0), -1, 8, 0);if (maxCorners < 1)maxCorners = 1;vector<Point2f> corners;double qualityLevel = 0.01;double minDistance = 10;bool useHarrisDetector= false;Mat cormat;goodFeaturesToTrack(src_gray, corners, maxCorners, qualityLevel, minDistance, Mat(), blockSize, useHarrisDetector, k);for (int i = 0; i < corners.size(); i+)circle(dst_norm_scaled, cornersi, 6, Scalar(255), 2, 8, 0);circle(src_copy, cornersi, 4, Scalar(0, 255, 0), 2, 8, 0);imshow(corners_window, dst_norm_scaled);imshow(source_window, src_copy);3 调试程序。调试结果:(1)检测六边形边长下面是五边形的边沿检测结果:(2) 检测六边形角点下面是五边形的角点检测结果:4 根据实验结果,撰写实验报告。六、实验报告1 根据实验结果,分析比较两种检测方法的测量精度。2 对这两种检测方法,分析并给出提高测量精度的可行性方案。3 本实验的心得体会。实验过程中遇到很多问题没办法解决。查过很多问题资料,找不出头绪,也把程序注释了下,理解了大部分的内容,但需要做的还很多。经过几天的专研,终于把实验做了出来,但结果并不是很理想,需要改进的地方还很多。希望再接再厉,在能将实验做出来的基础上,更加的理解所学习的内容,以及将所学习过的东西应用到实践中去。