我毕业设计做的是芯片引脚缺陷检测,用的是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 ==rowint 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。

效果:

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

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

[毕设笔记] 毕设问题汇总相关推荐

  1. Spark笔记——技术点汇总

    Spark笔记--技术点汇总 目录 · 概况 · 手工搭建集群 · 引言 · 安装Scala · 配置文件 · 启动与测试 · 应用部署 · 部署架构 · 应用程序部署 · 核心原理 · RDD概念 ...

  2. Hadoop笔记——技术点汇总

    Hadoop笔记--技术点汇总 目录 · 概况 · Hadoop · 云计算 · 大数据 · 数据挖掘 · 手工搭建集群 · 引言 · 配置机器名 · 调整时间 · 创建用户 · 安装JDK · 配置 ...

  3. Vue PC商城项目开发笔记与问题汇总

    Vue PC商城项目开发笔记与问题汇总 负责PC端商城项目,这也是人生第一个真正的项目.刚做了一天,就遇到不少问题,在这里列出自己的问题与解决办法,与大家交流,提升自己,希望以后不会掉进同一个坑里. ...

  4. 全志A33学习笔记及问题汇总

    全志A33学习笔记及问题汇总 全过程: 1.编译环境配置 首次编译,需要导入vstar方案的内核配置,进入linux3.4目录, 如果开启WIFI需修改a33_vstar_defconfig 1294 ...

  5. Linux学习笔记之基本操作汇总

    Linux学习笔记之基本操作汇总 图片放大了再看才清楚!!!! Linux cd ocd / root package ocd /user ocd -/ ocd ~ home ocd - ls ...

  6. 《基于深度学习的加密流量识别研究》-2022毕设笔记

    参考文献: 基于深度学习的网络流量分类及异常检测方法研究_王伟 基于深度学习的加密流量分类技术研究与实现_马梦叠 基于深度学习的加密流量识别研究综述及展望_郭宇斌 基于深度学习的加密流量算法识别研究_ ...

  7. 物联网毕设 STM32题目项目汇总 - 100例

    文章目录 1前言 2 STM32 毕设课题 3 如何选题 3.1 不要给自己挖坑 3.2 难度把控 3.3 如何命名题目 1前言

  8. 软件工程毕设项目推荐 选题汇总

    文章目录 0 简介 1 如何选题 2 最新软件工程毕设选题 3 最后 0 简介 学长搜集分享最新的软件工程业专业毕设选题,难度适中,适合作为毕业设计,大家参考. 学长整理的题目标准: 相对容易 工作量 ...

  9. 毕业设计 2023-2024年最新信息管理专业毕设选题题目推荐汇总

    文章目录 0 前言 1 java web 管理系统 毕设选题 2 java web 平台/业务系统 毕设选题 3 游戏设计.动画设计类 毕设选题 (适合数媒的同学) 4 算法开发 5 数据挖掘 毕设选 ...

最新文章

  1. Golang反射机制的实现分析——reflect.Type类型名称
  2. DH1766线性三路可编程直流电源
  3. 在MyEclipse中导入做好的java项目出现错误The project cannot be built until build path errors are resolved
  4. Aspectj 实现Method条件运行
  5. 微信小程序- 初试小程序之tabbar(选项卡,底部导航)的使用
  6. 配置postfix+dovecot+mysql+postfixadmin+squirrelmail 邮件系统笔记
  7. java加载dll UnsatisfiedLinkError: no mydll in java.library.path
  8. java jsonarray 追加_我们如何在Java中将JSONArray添加到JSONObject?
  9. C/C++的64位整型
  10. 局部内部类如何访问外部类方法中变量
  11. C++指针和引用的区别
  12. Mac查看占用端口进程
  13. 使用 Netsh.exe 配置 WinHTTP 的代理设置
  14. ESP8266 WIFI模块开发入门1 开发环境搭建
  15. FITC-WFA荧光素标记紫藤凝集素(WFA,WFL)
  16. Python教程三:使用Flask搭建web服务
  17. Nginx + ModSecurity 报错
  18. TM4C123系列(三)————PWM输出
  19. 2/8法则系列 | 你真的了解二八法则吗?
  20. 大数据时代,我们必守的三条底线,大数据杀熟,不可忍

热门文章

  1. 今天教大家用虚拟机做cpa
  2. 全国计算机等级考试c语言设计题,全国计算机等级考试 《C语言程序设计》习题.doc...
  3. 选择大于努力?看涛思数据两名90后如何获得“胡润U30企业领袖奖”
  4. 企业工程行业管理系统源码-专业的工程管理软件-提供一站式服务
  5. Oracle删除链接用户
  6. 凭借这份pdf,必拿下蚂蚁金服、字节跳动、小米等大厂的offer
  7. java rtf转换word_把Doc文档转换成rtf格式
  8. Unity3d C#用UGUI系统实现类似于哔哩哔哩(B站)的弹幕效果功能(含源码)
  9. Win10下LoadRunner12 下载安装汉化图文教程(含LoadRunner安装包)
  10. 科研工具流1——Zotero管理文献