• 摄像头距离标定方法研究(得到像素和毫米的转换比)


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

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

         比如我获得这样的图片。这幅图片的获取,基于我自己改造的图像处理支架,对于普通的实验来说,已经比较纯净了。由于使用的是钢尺,反光比较厉害。为了便于标定,我将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;
    }
     





    附件列表

  • 相关阅读:
    win10下python环境变量设置
    c++ primer第15章这几个例子中的构造函数形式不太理解
    ++与*
    C++符号优先级
    56-Remove Linked List Elements
    55. Binary Tree Preorder Traversal
    54. Flatten Binary Tree to Linked List
    野指针--内存泄漏--缓存区溢出--栈溢出
    数组指针和指针数组的区别
    53-Linked List Cycle II
  • 原文地址:https://www.cnblogs.com/jsxyhelu/p/ruler.html
Copyright © 2020-2023  润新知