机器视觉课程设计学院机电工程学院专业机械设计制造及其自动化(微电子制造专业方向)年级班别XXXXXXXXXXXXXXXX学号XXXXXXXXXXXXX学生姓名XXXXXXXXX指导教师XXXXXXXXX2015年1月18日21问题描述1.1基本目标显示一张图片(包含一个矩形或一个圆),测量矩形的长宽或圆的直径。完成得及格分,扩展有加分!1.2基本要求“机器视觉”考试结果要求独立在计算机上完成,建议使用VisualC++和OpenCV实现一个具有视觉捕捉、图像显示、尺寸测量等功能的对话框程序,其中必须完成对圆盘形零件圆心与直径和矩形零件长与宽尺寸测量内容。在教师提供的基本框架程序基础上,修改、补充界面和功能。2程序及其算法2.1检测与计算圆半径的程序思路:从图片中间横扫取点得M_Point[0],M_Point[1](x坐标相加除2的圆心的x坐标)中间纵向取点得M_Point[2],M_Point[3](y坐标相加除2的圆心的y坐标)圆上四个点到圆心的距离(半径)取平均值,输出为半径。要求图片3程序如下:doublec_DialogTeclarn::f_MakeCircle(doublee_dThreshold){if(NULL==m_pIplImageSource){return0;}//定义变量存图像的宽,高,行像素intq_iWidth=m_pIplImageSource-width;intq_iHeight=m_pIplImageSource-height;intq_iWidthStep=m_pIplImageSource-widthStep;uchar*q_pchDataImage=(uchar*)m_pIplImageSource-imageData;CvPointM_Point[4]={};//存放检索出的四个点循环检索//01纵扫for(intCycle_Y=1;Cycle_Yq_iHeight;Cycle_Y++){if(e_dThresholdq_pchDataImage[q_iWidth/2+q_iWidthStep*(Cycle_Y-1)]){M_Point[0].x=q_iWidth/2;M_Point[0].y=Cycle_Y;}}显示图片4for(intCycle_Y=q_iHeight;Cycle_Y1;Cycle_Y--){if(e_dThresholdq_pchDataImage[q_iWidth/2+q_iWidthStep*(Cycle_Y-1)]){M_Point[1].x=q_iWidth/2;M_Point[1].y=Cycle_Y;}}for(intCycle_X=1;Cycle_Xq_iWidth;Cycle_X++){if(e_dThresholdq_pchDataImage[Cycle_X+q_iWidthStep*(q_iHeight/2-1)]){M_Point[2].x=Cycle_X;M_Point[2].y=q_iHeight/2;}}for(intCycle_X=q_iWidth;Cycle_X1;Cycle_X--){if(e_dThresholdq_pchDataImage[Cycle_X+q_iWidthStep*(q_iHeight/2-1)]){M_Point[3].x=Cycle_X;M_Point[3].y=q_iHeight/2;}}for(inti=0;i4;i++)//画边界圆{cvCircle(m_pIplImageSource,M_Point[i],8,cvScalarAll(127),2);}intRidius=0,clear=0;intcircle_y=abs(M_Point[1].y+M_Point[0].y)/2;intcircle_x=abs(M_Point[3].x+M_Point[2].x)/2;5floatc=0,j=0;for(inti=0;i4;i++){j=(M_Point[i].x-circle_x)*(M_Point[i].x-circle_x)+(M_Point[i].y-circle_y)*(M_Point[i].y-circle_y);c=c+sqrt(j);}Ridius=c/4;//在窗口中显示长和高charch1[10],ch2[10];itoa(Ridius,ch1,10);itoa(clear,ch2,10);SetDlgItemText(IDC_LONG,ch1);SetDlgItemText(IDC_SHORT,ch2);CWnd*e_pCWndPicture=this-GetDlgItem(ID_PICTURE_DISPLAY);f_ControlShowImage(m_pIplImageDisplay,e_pCWndPicture,m_pIplImageSource);cvSaveImage(_T(.//Result_Image.jpg),m_pIplImageSource);return0;}2.2检测与计算矩形长和宽的程序思路:这个程序主要包括:打开摄像头---保存图片(拍照)---加载刚刚保存的图片---找出点并计算长和高四个按钮,每一个按钮包含下面的一段代码,拍摄的图片保存为CurrentImage.jpg,这里事先保存了一张同名的图片,所以可以直接点击LoadImage读取。2.2.1打开摄像头程序voidc_DialogTeclarn::OnBnClickedButtonOpenCamera(){CvCapture*q_pCvCapture=cvCreateCameraCapture(0);if(NULL==q_pCvCapture){return;6}IplImage*q_pIplImageCapture=cvQueryFrame(q_pCvCapture);if(NULL==q_pIplImageCapture){return;}if(NULL!=m_pIplImageSource){cvReleaseImage(&m_pIplImageSource);m_pIplImageSource=NULL;}m_pIplImageSource=cvCloneImage(q_pIplImageCapture);cvReleaseCapture(&q_pCvCapture);CWnd*e_pCWndPicture=this-GetDlgItem(ID_PICTURE_DISPLAY);f_ControlShowImage(m_pIplImageDisplay,e_pCWndPicture,m_pIplImageSource);}注:绿色的为检测是否成功打开摄像头,蓝色的是读取摄像头拍摄的图片到内存,后面的语句是让图片在mfc窗口显示出来。2.2.2保存拍摄的照片程序voidc_DialogTeclarn::OnBnClickedButtonSaveImage(){//TODO:在此添加控件通知处理程序代码cvSaveImage(_T(.//CurrentImage.jpg),m_pIplImageSource);}2.2.3读取拍摄到的图片(读取文名字CurrentImage.jpg的图片)voidc_DialogTeclarn::OnBnClickedButtonLoadImage(){//TODO:在此添加控件通知处理程序代码if(NULL!=m_pIplImageSource){cvReleaseImage(&m_pIplImageSource);m_pIplImageSource=NULL;}m_pIplImageSource=cvLoadImage(_T(.//CurrentImage.jpg),0);CWnd*e_pCWndPicture=this-GetDlgItem(ID_PICTURE_DISPLAY);f_ControlShowImage(m_pIplImageDisplay,e_pCWndPicture,m_pIplImageSource);}2.2.4检测边上的点和计算长和高的函数思路是:第一步找到边上的点,设定一个变量e_dThreshold值为127,通过循环让7它与每一个像素的像素值进行比较。如果检测到一个点的像素值比127小,则这个点可能就是需要的点(黑色=0,白色=255)如果每个像素都要比较运算太多,所以上边两个点的检测是沿着图片长的的2/5分处和3/5分处向下检测,下边的点是沿着1/2处向上检测。第二步是用找到6个点的坐标算出三角形的面积,然后除以底边边长得到高。求三角形的面积用的是行列式的值等于三角形面积的2倍程序如下:doublec_DialogTeclarn::f_MakeRectangleWidth(doublee_dThreshold){//TODO:在此添加控件通知处理程序代码//定义一些点和变量intq_iWidth=m_pIplImageSource-width;intq_iHeight=m_pIplImageSource-height;intq_iWidthStep=m_pIplImageSource-widthStep;uchar*q_pchDataImage=(uchar*)m_pIplImageSource-imageData;intq_iXLeftTop=2*q_iWidth/5;intq_iXRightTop=3*q_iWidth/5;intq_iXBottom=q_iWidth/2;intq_iYLeftTop=2*q_iHeight/5;intq_iYLeftBottom=3*q_iHeight/5;intq_iYRightMid=q_iHeight/2;CvPointq_CvPointLeftTop,q_CvPointRightTop,q_CvPointBottom;CvPointq_CvPointLeft_Top,q_CvPointRight_Mid,q_CvLeft_Bottom;//求上下两边上的点,3个循环for(intq_iCycleHeight=0;q_iCycleHeightq_iHeight;q_iCycleHeight++){if(e_dThresholdq_pchDataImage[q_iCycleHeight*q_iWidthStep+q_iXLeftTop]){q_CvPointLeftTop.x=q_iXLeftTop;q_CvPointLeftTop.y=q_iCycleHeight;break;}}for(intq_iCycleHeight=0;q_iCycleHeightq_iHeight;q_iCycleHeight++){if(e_dThresholdq_pchDataImage[q_iCycleHeight*q_iWidthStep+q_iXRightTop]){q_CvPointRightTop.x=q_iXRightTop;8q_CvPointRightTop.y=q_iCycleHeight;break;}}for(intq_iCycleHeight=q_iHeight-1;q_iCycleHeight=0;q_iCycleHeight--){if(e_dThresholdq_pchDataImage[q_iCycleHeight*q_iWidthStep+q_iXBottom]){q_CvPointBottom.x=q_iXBottom;q_CvPointBottom.y=q_iCycleHeight;break;}}//求左右两边上的点,3个循环for(intq_iCycleWidth=0;q_iCycleWidthq_iHeight;q_iCycleWidth++){if(e_dThresholdq_pchDataImage[q_iCycleWidth+q_iWidthStep*(q_iYLe