[毕设&笔记] 毕设问题汇总

简介: [毕设&笔记] 毕设问题汇总

   我毕业设计做的是芯片引脚缺陷检测,用的是halcon+MFC,其实说白了,就是将halcon的程序进行导出、拆分,嵌入到mfc各个部件中,从而实现整体功能。因为研一上学期学的其实是opencv+qt5,所以这部分不是很熟。这里主要将我做的毕设的过程,以及在这过程中遇到的问题记录下来,留作以后参考,也算是经验的积累。

描述一:在检测引脚平面度的时候,需要将引脚底部中心点画出来,可利用halcon助手的基于互相关的模板匹配例子,导出后可拆分成打开原图、设定模板、匹配图三个部分,但在第三个匹配图中我想直接把halcon里面的关于引导中心点十字光标显示出来,如图:

       但这部分程序(如下)只有输出图(参数一),各中心的坐标(hv_MatchingCol为x坐标, hv_MatchingRow为y坐标),但是没有句柄,自己创建一个句柄有错误,不知道可不可以直接显示输出图(有大神知道的可以告知一下,感激不尽)。

GenCrossContourXld(&ho_TransContours, hv_MatchingRow, hv_MatchingCol, 20, hv_MatchingAngle);

最后没有办法,只能通过上边的坐标直接通过画笔挨个把点画出来。

问题一:如何获取引脚中心点的坐标?

解决:

上边的GenCrossContourXld()函数给出了 HTuple类型的中心点行列坐标,需要将HTuple类型转换成int/double类型的。

问题二:如何把坐标点画到图片上(画笔、画刷的用法),而不是图片所在的控件上?

解决:

为你图片所在的控件添加一个变量,比如m_pic,然后在OnPaint()中加入

//调用实现图片打开功能的函数
OnBnClickedButton2();
//例:在图片上画一个圆
CDC *pDC = m_pic.GetWindowDC();
CPen pen(PS_SOLID,6,RGB(255,0,0));
pDC->SelectObject(&pen);
pDC->Ellipse(50,50,101,101);

描述二:当时可以将点画在图片上面了,但是当点比较大的时候,需要将图片所在的控件放大,才能显示在图片上,所以我猜测坐标可能是相对于图片的像素大小而言的,也就是像素坐标,要想在mfc控件上显示准确的坐标,一种方法是将控件放大到和图片像素大小一下(显然不靠谱),而另一种方法就需要将坐标进行一个缩放了。

问题三:如何将相对于图片像素大小的坐标,进行缩放,准确显示到Picture Control上的图片上?

解决:

当不进行缩放时,在原始图片上显示的点坐标,

到了mfc对话框中,可能会显示不出来(控件太小了),将控件放大后,可能会在任何位置显示,不会准确显示到引脚中心,所以需要将坐标进行缩放,依据的原理是:

只需要将相对于图片大小的坐标缩放到相对于控件大小的即可,可通过公式控件宽/图片宽=x“/x=y”/y, 即可求出缩放后的坐标(x“,y”),而图片宽,控件宽能求,(x,y)已知。

代码:

//获取控件尺寸和位置
  CRect rectCtrl;
  CStatic *p = (CStatic*)GetDlgItem(IDC_STATIC3);
  //p->MoveWindow(100, 100, 100, 100);//更改控件大小并移动其到指定位置
  p->GetWindowRect(rectCtrl);
  this->ScreenToClient(rectCtrl);
  //GetDlgItem(IDC_STATIC_TEST)->GetClientRect(rectCtrl);
  int width =  rectCtrl.Width();
  int height =  rectCtrl.Height();
  OnBnClickedButton1();
  //获取图片尺寸(pic为图片的类型)
    int cx = pic.GetWidth();
    int cy = pic.GetHeight();
  OnBnClickedButton2();
  CDC *pDC = m_pic.GetWindowDC();
  CPen pen(PS_SOLID,4,RGB(255,0,0));
  pDC->SelectObject(&pen);
  //point.x ==col
  //point.y ==row
  int i=0;
  int j=0;
  for(;i<5,j<5;i++,j++)
  {
  double ti = hv_MatchingCol[i].D(); 
  double tj = hv_MatchingRow[j].D();
  pDC->Ellipse((ti/cx)*width,(tj/cy)*height,(ti/cx)*width+1,(tj/cy)*height+1);
  }

效果:

问题四:c++ 如何将多个点存入容器?

描述:我说的将多个点存入容器,不是自己手动一个点一个点的存,那样感觉很蠢,而且换一张和之前点数不一样的图片后就不行了,不具有普遍性。

解决:

首先定义一个结构:

struct Point
 {
    double x;
    double y;
 };

然后,没改之前的程序是下面这样的,

vector<Point> points;
Point point1;
for(int i = 0; i<5;i++)
{
  point1.x=hv_MatchingCol[i].D();
  point1.y=hv_MatchingRow[i].D();
  points.push_back(point[i]);
}

       因为point1.x,point1.y的值在不断更新,这就导致容器points里面存入的值不断被新进来的值给替换掉,而不是都存入容器points中。

       解决办法就是point.x与hv_MatchingCol[i].D(),point.y与hv_MatchingRow[i].D();的值一一对应,而不是前面的值一直在更新。

改进之后的程序:

vector<Point> points;
Point point[5];
for(int i = 0; i<5;i++)
{
  point[i].x=hv_MatchingCol[i].D();
  point[i].y=hv_MatchingRow[i].D();
  points.push_back(point[i]);
}

注:halcon 里面HTuple类型的 hv_MatchingCol,hv_MatchingCol里面之前就各有五个数,而hv_MatchingCol[i].D()是将HTuple类型转换为double类型。

问题五:将多个点拟合成一条直线,并求出点到直线的最大距离和最小距离。

参考:https://blog.csdn.net/liyuanbhu/article/details/50866802

描述:

  • 最小二乘法直线拟合(不是常见的一元线性回归算法)
  • 将离散点拟合为 a x + b y + c = 0 型直线
  • 假设每个点的 X Y 坐标的误差都是符合 0 均值的正态分布的。
  • 与一元线性回归算法的区别:一元线性回归算法假定 X 是无误差的,只有 Y 有误差。

解决:

可以与上面存入点的容器对接,利用已知点,求出直线方程中的系数a,b,c。

double a, b, c;
  int size = points.size();
    if(size < 2)
     {
         a = 0;
         b = 0;
         c = 0;
     }
     double x_mean = 0;
     double y_mean = 0;
     for(int i = 0; i < size; i++)
     {
         x_mean += points[i].x;
         y_mean += points[i].y;
     }
     x_mean /= size;
     y_mean /= size; //至此,计算出了 x y 的均值
     double Dxx = 0, Dxy = 0, Dyy = 0;
     for(int i = 0; i < size; i++)
     {
         Dxx += (points[i].x - x_mean) * (points[i].x - x_mean);
         Dxy += (points[i].x - x_mean) * (points[i].y - y_mean);
         Dyy += (points[i].y - y_mean) * (points[i].y - y_mean);
     }
     double lambda = ( (Dxx + Dyy) - sqrt( (Dxx - Dyy) * (Dxx - Dyy) + 4 * Dxy * Dxy) ) / 2.0;
     double den = sqrt( Dxy * Dxy + (lambda - Dxx) * (lambda - Dxx) );
     if(fabs(den) < 1e-5)
     {
         if( fabs(Dxx / Dyy - 1) < 1e-5) //这时没有一个特殊的直线方向,无法拟合
         {
         }
         else
         {
             a = 1;
             b = 0;
             c = - x_mean;
         }
     }
     else
     {
         a = Dxy / den;
         b = (lambda - Dxx) / den;
         c = - a * x_mean - b * y_mean;
     }
  CDC *pDC1 = m_pic.GetWindowDC();
  CPen pen1(PS_SOLID,1,RGB(0,0,255));
  pDC1->SelectObject(&pen1);
  pDC1->MoveTo((points.at(0).x)/cx*width,-((a*points.at(0).x+c)/b)/cy*height);
  pDC1->LineTo((points.at(4).x)/cx*width,-((a*points.at(4).x+c)/b)/cy*height);

效果:

求出点到直线的最大距离和最小距离:

//求出引脚中心点到标注直线的距离,并存入容器dis中
  vector<double>dis;
  for(int i =0;i<size;i++)
  {
  double d1 = a * points.at(i).x+b * points.at(i).y+c;
  double d2 = sqrt(a*a+b*b);
  double d = sqrt(d1/d2*d1/d2);
  dis.push_back(d);
  }
  //求出距离最大值,最小值
  double min,max;
  max = min = dis.at(0);
  for (int i = 0; i < size; i++)
  { 
    if (max < dis.at(i))
      max = dis.at(i);
    if (min > dis.at(i))
      min = dis.at(i);  
  }

问题六:在MFC中Edit控件上显示含小数点的数,并可以控制小数点后的位数。

以double类型小数0.274002149218631为例

解决:

方法一:精确到小数点后一位

1)首先为控件Edit添加一个CString类型的变量

2)添加代码:

CString s;
  s.Format("%.lg", max); //显示一位小数
  max_edit =s;
  UpdateData(FALSE);

效果:

方法二:原来多少位的小数,就显示多少位的:

1)为编辑框Edit添加一个double类型的变量min_edit

2)添加代码:

min_edit = min;
    UpdateData(FALSE);//把控件关联的变量值“刷到”控件上显示

效果:

方法三:任意控制小数点后的位数:

1)为编辑框Edit添加一个double类型的变量min_edit

2)添加代码:

min_edit = max;
  min_edit = floor(min_edit * 1000.000f + 0.5) / 1000.000f;
    UpdateData(FALSE);//把控件关联的变量值“刷到”控件上显示

上面是精确到小数点后三位,如果精确到小数点后两位,改成100.000f。

效果:

问题七:打开多张图片后,第二张之后的所有图片显示的引脚中心点拟合出的直线都是第一张图的芯片引脚直线,如图:

解决:

       之前一直奇怪为什么引脚中心点更新出来了,而画的直线没有更新出来,一直再找如何对画的图进行更新。后来仔细想了一下,发现第二次打开图片后,由于容器里面存放的第一张图片中芯片引脚的坐标点还在,再打开第二张图片后,虽然第二张图片的芯片引脚数据存到容器里面了,但是在第一张图片芯片引脚数据之后,所以画的还是第一张图片的直线,而画坐标点没有用到容器,将坐标提取出来就直接画了,自然没有问题。最后在画完直线后,将容器里芯片引脚中心坐标数据清空,问题解决。

目录
相关文章
|
7月前
|
机器学习/深度学习 编解码 区块链
毕设选题应当注意什么-如何选题-附相关解决案例资料
毕设选题应当注意什么-如何选题-附相关解决案例资料
|
2月前
|
传感器 监控 JavaScript
千套单片机\stm32毕设课设题目及资料案列-干货分享
为帮助电子工程领域的学习者顺利毕业或掌握更多专业知识,我们精心整理了一系列单片机和STM32相关的题目及资料案例。这些资源覆盖了从毕业设计到课程设计的各个方面,包括但不限于智能小车、温度控制系统、无线通信、智能家居等多个领域。每项设计都配有详细的原理图、仿真图以及完整的文档资料,旨在帮助学生深入理解理论知识的同时,提高实际动手操作能力。无论是初学者还是有一定基础的学生,都能从中找到适合自己的项目进行实践探索。
292 8
|
5月前
|
传感器 物联网 定位技术
毕设(一)——概述
毕设(一)——概述
|
6月前
|
数据安全/隐私保护
单片机课程设计——基于C51电子密码锁(源代码)
单片机课程设计——基于C51电子密码锁(源代码)
计算机毕设怎么选题
计算机毕设怎么选题
141 1
|
7月前
|
小程序 搜索推荐 JavaScript
最新计算机软件毕业设计选题大全
最新计算机软件毕业设计选题大全
68 0
|
7月前
|
前端开发 NoSQL Redis
毕设系统
毕设系统
基于51单片机的智能电子秤设计课程设计毕业设计
具体功能: 1、数码管显示当前的重量,单位是g; 2、有去皮和清零功能,可以通过三个按键微调校准重量; 3、最大称重9.999kg,超过最大量程声光报警。
221 0
|
搜索推荐 Shell
单片机面试的问题1
单片机面试的问题1
67 0
|
小程序 搜索推荐
计算机毕设选题-基于微信小程序的四六级小程序
重要的事情说三遍,可白嫖,可白嫖,可白嫖!!! 源码下载链接:docs.qq.com/doc/DYm5DSlBWZEplalBP 基于微信小程序的四六级助手,包括管理端和小程序端两部分。管理端包含单词管理、翻译管理、写作管理、资料管理、资讯管理和听力管理六个模块,可以实现对相关内容的上传和管理。小程序端包括首页、资讯、单词和我的四个模块,可以帮助用户进行听力练习、翻译文章和写作文章的查看,单词的学习和错题本的管理。同时,小程序还基于艾宾浩斯曲线进行消息推送,提醒用户回到小程序学习巩固知识。本款四六级助手小程序的设计和实现可以为广大四六级考生提供便捷的学习工具和服务,有着很好的实用性和推广价值