自动测量硬币直徑(opencv)C++实现

条件:opencv 4.5 、Qt5.13 、DroidCam 6.0

操作系统:ubuntu 20

硬件: 电脑、手机

待测物:硬币

一、搭建交互界面

1、首先从图像源上可以分成是本地图片、相机成像(内设、外设),因此这一步设计三个图像源获取方式;分别是笔记本前置摄像头、外置摄像头(手机通过DroidCam)。

这个直接设计为下拉选项框(QComboBox),然后通过获取选项index来读取不同输入源。

2、开始按钮

直接ui上添加QPushButton,然后修改textlabel为“开始”,没有其他骚操作。

3、显示所读取的图像以及处理后的图像

这里使用两个Qlabel进行图像的显示。

4、测试结果的显示

这里主要有测试数据的显示和测试结果是否合格的显示,运用Qlable显示pass/fail的图片,以及运用QlineEdit显示测试数据。

 由于本项目与其他项目共有一个ui,因此会有一些其他的控件在主界面中。

二、代码部分

1、下拉框初始化、以及信号量的初始化,

    QStringList cameraList = {"前置摄像头","外置摄像头","本地图片"};
    ui->cBox_camera->addItems(cameraList);
    hasObject = false;
  

2、图像源的选择

    connect(ui->cBox_camera,QOverload<int>::of(&QComboBox::activated),this,[=](int index){
        ImageSource = index;//图像源标记
        if(index == 2){
        ui->label_filepath->show();
        ui->lineEdit_filepath->show();
        ui->btn_file->show();
        }
        else{
            FilePathInit();
        }
    });
    //输入图像切换

3、点击开始按钮后执行的函数

    connect(ui->btn_start,&QPushButton::clicked,this,[&]()mutable{
        working = true;//工作状态设为true,当点击停止按钮时切换false
        cv::Mat src,dst;
        if(ImageSource==2){//以读取本地图片作为输入图像
            QString Imgpath = ui->lineEdit_filepath->text();
            qDebug() << Imgpath << endl;
            if(Imgpath.isEmpty()){
            DemindMessage("Error","The FilePath Is Invalid\n");//文件路径为空时进行信息提醒
            }
            else{
            src = cv::imread(Imgpath.toStdString());
            cv::imshow("pic",src);
            SrcImageDisplay(src);
            if(CurrentStatus==0){
            DefaultPro(src,dst);//自定义默认模式下处理函数
            }
            else if(CurrentStatus == 1){
            MeasurePro(src,dst);//自定义处理函数
            }
            else{
            DetectPro(src,dst);//自定义处理函数
            }
            }
            MatToQImage(dst);//自定义图像类型Mat To QPixel转换函数
        }
        else{//以读取视频设备作为输入图像
            int tmp;//因为设备号只有1、2可用,这里转换一下
            if(ImageSource==0){
            tmp = 1;
            }
            else{
            tmp = 2;
            }
            cv::VideoCapture cap(tmp);//读取相机图像
            while(cap.read(src)){
                if(cv::waitKey(20)==27||!working){
                    break;
                }
                if(CurrentStatus==0){
                    cv::waitKey(500);//这里延时0.5s,
                }
                //SrcImageDisplay(src);
                LabelToImage(src,ui->label_src);
                if(CurrentStatus==0){
                std::cout << "default" << std::endl;
                DefaultPro(src,dst);
                }
                else if(CurrentStatus == 1){
                MeasurePro(src,dst);
                }
                else{
                DetectPro(src,dst);
                }
                LabelToImage(dst,ui->label_dst);
            }
            cap.release();
        }
src.release();
dst.release();
    });//启动
        std::vector<float> rad;//储存物体直徑
        CircleImagePro(src,dst,rad);
        if(!hasObject){
            return;
        }//若未检测到目标则返回
        for(size_t i=0;i<rad.size();++i){
           if(rad[i]>float(21.50)||rad[i]<float(19.50)){//判断是否合格
               ui->label_result->setStyleSheet("image:url(:/img/fail.jpeg)");
           }
           else{
               ui->label_result->setStyleSheet("image:url(:/img/pass.jpeg)");
           }
        }

目标检测代码(圆形):

    using namespace cv;
    using namespace std;
    QStringList TestData;
    src.copyTo(dst);
    float c = float(20.5)/float(68.9);
    vector< vector<cv::Point> > contours;
    //图像预处理
    Mat img;
    cvtColor(src,img,COLOR_BGR2GRAY);
    GaussianBlur(img,img,cv::Size(3,3),1);
    Canny(img,img,50,150,3);
    Mat kernel = getStructuringElement(MORPH_RECT,Size(3,3));//获取卷积核
    dilate(img,img,kernel,cv::Point(-1,-1),3);
    erode(img,img,kernel,Point(-1,-1),2);
    findContours(img,contours,RETR_EXTERNAL,CHAIN_APPROX_SIMPLE);
    img.release();
    vector< cv::Point2f > center(contours.size());
    vector<float> rad(contours.size());
    if(contours.size() == 0){
        NotFoundObject(src,dst);
        ui->textEdit_testdata->setText("未在图像中发现检测物!请重新检测。");
        return;
    }
    else{
        hasObject = true;
    }
    for(size_t i =0;i<contours.size();++i){
        minEnclosingCircle(contours[i],center[i],rad[i]);
        radius.push_back(rad[i]*c);
    }
    for(size_t j=0;j<center.size();++j){
        string str = "radius: ";
        string str1;
        float r = 0.0;
        circle(dst,center[j],rad[j],Scalar(0,0,255),1);
        r = rad[j]*c;
        str1 = format("%.4f",r);
        str.insert(str.end(),str1.begin(),str1.end());
        TestData.append(QString::fromStdString(str));
        putText(dst,str,center[j],1,2,Scalar(0,255,0),2,8);
    }
    QStringTextOutput(TestData);
    TestData.clear();

硬币测量

  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值