zoukankan      html  css  js  c++  java
  • 摄像头距离标定方法研究(得到像素和毫米的转换比)

         一般在高精度测量时需要做以下几个标定,一光学畸变标定(如果您不是用的软件镜头,一般都必须标定),二投影畸变的标定,也就是因为您安装位置误差代表的图像畸变校正,三物像空间的标定,也就是具体算出每个像素对应物空间的尺寸。

          前两者应该都可以通过“张正友”标定方法进行解决;对于空间的标定,基本上都是通过获得比对现实中的已经知道长度的物体,获得像素当量到长度的转化。
          现实拍摄的物体,或多或少会有噪音干扰,在标定的过程中还需要图像处理算法进行纠正。

         比如我获得这样的图片。这幅图片的获取,基于我自己改造的图像处理支架,对于普通的实验来说,已经比较纯净了。由于使用的是钢尺,反光比较厉害。为了便于标定,我将10厘米和20厘米两个地方用绿色胶带缠绕住。
        下一步,就是要获得关键区域。通过GOPre的分析,原始图像在YUV域下,比较方便分割
    编写代码分割,阈值分析
        Mat src = imread("E:\sandbox\1.bmp");
        Mat dst;
        Mat tmp;
        vector<MatmatSplit;
        cvtColor(src,tmp,COLOR_BGR2YUV);
        split(tmp,matSplit);
        dst = matSplit[1];
        threshold(dst,dst,100,255, COLOR_BGR2Lab)  );
        cv::waitKey();
    这个时候还是有噪音的,但是已经比较理想了。最合适的方法就是投影分析。由于GOCVHelper中的投影分析本来是对字符投影进行分割的,所以需要适当地修正。
    void projection4ruler(Mat srcintdown1,intup2 ,int direction){
        Mat tmp = src.clone();
        vector<intvdate;
        if (DIRECTION_X == direction){
            for (int i=0;i<tmp.cols;i++){
                Mat data = tmp.col(i);
                int itmp = countNonZero(data);
                if (itmp > 10)
                {
                    int jjj=0;
                }
                vdate.push_back(itmp);
            }
        }else{
            for (int i=0;i<tmp.rows;i++){
                Mat data = tmp.row(i);
                int itmp = countNonZero(data);
                vdate.push_back(itmp);
            }
        }
        //过滤掉所有噪音
        //寻找第一个下边沿和第二个上边沿
        down1 = 1;
        up2   = src.cols - 1;
        for (int i=0;i<tmp.cols-1;i++)
        {
            if (vdate[i] >=  100 && vdate[i+1] < 100)
            {
              down1 = i;
              break;
            }
        }
        for (int idown1;i<tmp.cols - 1;i++)
        {
            if (vdate[i] < 100 && vdate[i+1] >= 100)
            {
                up2 = i;
                return;
            }
        }
    }
    寻找并且标注出来,非常准确。
    图上(1767 - 771  =  996)对于10厘米,那么,那么1个像素相当于0.1毫米(这个整数只是巧合)
     
    多次测量,验证算法的稳定性,并运用于实际项目。
     
    小结
    基于算法库和成熟的思路,能够加速解决问题速度。
    比较好的视觉环境也很重要。
    附全部代码
    //GoCvHelper的demo程序
    #include "stdafx.h"
    #include <iostream>
    #include "opencv2/core/core.hpp"
    #include "opencv2/highgui/highgui.hpp"
    #include "opencv2/imgproc/imgproc.hpp"
    #include "GoCvHelper.h"
     
    using namespace std;
    using namespace cv;
    using namespace GO;
    #define  VP  vector<cv::Point>  //用VP符号代替 vector<point>
     
    void projection4ruler(Mat srcintdown1,intup2 ,int direction){
        Mat tmp = src.clone();
        vector<intvdate;
        if (DIRECTION_X == direction){
            for (int i=0;i<tmp.cols;i++){
                Mat data = tmp.col(i);
                int itmp = countNonZero(data);
                if (itmp > 10)
                {
                    int jjj=0;
                }
                vdate.push_back(itmp);
            }
        }else{
            for (int i=0;i<tmp.rows;i++){
                Mat data = tmp.row(i);
                int itmp = countNonZero(data);
                vdate.push_back(itmp);
            }
        }
        //过滤掉所有噪音
        //寻找第一个下边沿和第二个上边沿
        down1 = 1;
        up2   = src.cols - 1;
        for (int i=0;i<tmp.cols-1;i++)
        {
            if (vdate[i] >=  100 && vdate[i+1] < 100)
            {
              down1 = i;
              break;
            }
        }
        for (int idown1;i<tmp.cols - 1;i++)
        {
            if (vdate[i] < 100 && vdate[i+1] >= 100)
            {
                up2 = i;
                return;
            }
        }
    }
     
    int _tmain(int argc_TCHARargv[])
    {    
        Mat src = imread("E:\sandbox\1.bmp");
        Mat dst;
        Mat tmp;
        int up1 = 0;
        int down2 = 0;
     
        vector<MatmatSplit;
        cvtColor(src,tmp,COLOR_BGR2Lab);
        split(tmp,matSplit);
        dst = matSplit[1];
        threshold(dst,dst,100,255,THRESH_OTSU);
        threshold(dst,dst,0,255,THRESH_BINARY_INV);//以白色为有数据
     
        projection4ruler(dst,up1,down2,DIRECTION_X);
        line(src,Point(up1,0),Point(up1,src.rows-1),Scalar(0,0,255),1);
        line(src,Point(down2,0),Point(down2,src.rows-1),Scalar(0,0,255),1);
        cv::waitKey();
        return 0;
    }
     





    附件列表

  • 相关阅读:
    zbb20181207 springboot @ConfigurationProperties使用
    zbb20181206 logback,lombok 默认日志logback配置解析
    Spring Boot (8) 全局异常处理
    Spring Boot (7) JdbcTemplate访问数据库
    Spring Boot (6) Spring Data JPA
    Spring Boot (4) 静态页面和Thymeleaf模板
    Spring Boot (3) 热部署devtools
    Spring Boot (2) Restful风格接口
    Spring Boot (1) 构建第一个Spring Boot工程
    idea使用maven搭建ssm框架实现登陆商品增删改查
  • 原文地址:https://www.cnblogs.com/jsxyhelu/p/ruler.html
Copyright © 2011-2022 走看看