zoukankan      html  css  js  c++  java
  • 寻找激光的交叉点

    这是一个来自网友的提问:

    这是一张激光图片,需要得到3横3竖的交点,其中的圆和X是用了测试仿射变换的。
    一、图片分析
    大像素、单通道。
     
    二、思路分析
    必须在量化的基础上,寻找这9个焦点的“固有特征”;至于9个点之间的排序,那是简单问题。
     
    三、算法实践
    1、这样一个图像,单通道所以无法做HSV分解;必须考虑到光照影响,所以不能采用OSTU;经验告诉我,直接bin能够得到较好效果。
    2、得到的结果,可能会有孤立点,需要通过形态学方法去除
    参考相关文章
    需要做的是”开“运算。根据观察,我们采用5*5的核心。
    得到的结果是奇异点全部消失,但是现有轮廓会有所衰弱。
    3、进一步执行细化,精确定位;或者也会出现细微偏差
    4、那么,这个图像质量,我们如何建立特征提取模型了?
    对于这样一个点
    4个象限,那么对于我们这些交点来说,肯定是有特征的,
    比如上图表示,对于这幅图像中的所有的点,可以区分为1-4个象限;就目前这4个象限中来看,每个象限都存在有数据的区域。
    但是经过编码发现,由于原图中有圆形等其他图像,干扰比较大,所以可以进一步增加约束为“寻找所有该点本身、其左边、右边、上边、下边都为255的点“
    由于这是一个比较明显的特征,所以我们可以直接编写代码去提取。
        //遍历图像,这里我在遍历的时候缩了一个像素
        vector<PointvecPoints;
        for(int i=1;i<src.rows - 1;i++){     
            for(int j=1;j<src.cols - 1;j++){       
                if ( src.at<uchar>(i,j) == 255) //首先该像素要有数据
                {    
                    if (src.at<uchar>(i-1,j) == 255 && src.at<uchar>(i+1,j) == 255 && src.at<uchar>(i,j-1) == 255 && src.at<uchar>(i,j+1)==255)
                    {
                        vecPoints.push_back(Point(j,i));
                    }
                }
                     
            }
        }
        //在底图上进行绘制
        cvtColor(srcClone,srcClone,COLOR_GRAY2BGR);
        for (int i = 0;i<vecPoints.size();i++)
        {
            circle(srcClone,vecPoints[i],10,Scalar(0,0,255),-1);
        }
    并且在原图上进行绘图,得到以下结果
    5、这个时候,我们要对得到的有限的点进行补全和排序
    需要注意的是这几个点本身肯定是有位置关系的,如果基本符合横平竖直的条件的话,我们可以做投影。但是具体情况还是要根据项目原始需求进行。
    //对得到的有限的点进行补全和排序
        vector<intvup;
        vector<intvdown;
        projection2(srcBoard,vup,vdown,1);
     
    此外,对可能出现的异常情况,也应该有很好的控制。
     
     
    附录:
    其实在这个程序中,比较关键的,处理解体思路之外,应该就是细化函数(来自GOCVHELPER/GITHUB)
    //将 DEPTH_8U型二值图像进行细化  经典的Zhang并行快速细化算法
        //细化算法
        void thin(const Mat &srcMat &dstconst int iterations){
            const int height =src.rows -1;
            const int width  =src.cols -1;
            //拷贝一个数组给另一个数组
            if(src.data != dst.data)
                src.copyTo(dst);
            int n = 0,i = 0,j = 0;
            Mat tmpImg;
            uchar *pU, *pC, *pD;
            bool isFinished =FALSE;
            for(n=0; n<iterationsn++){
                dst.copyTo(tmpImg); 
                isFinished =FALSE;   //一次 先行后列扫描 开始
                //扫描过程一 开始
                for(i=1; i<height;  i++) {
                    pU = tmpImg.ptr<uchar>(i-1);
                    pC = tmpImg.ptr<uchar>(i);
                    pD = tmpImg.ptr<uchar>(i+1);
                    for(int j=1; j<widthj++){
                        if(pC[j] > 0){
                            int ap=0;
                            int p2 = (pU[j] >0);
                            int p3 = (pU[j+1] >0);
                            if (p2==0 && p3==1)
                                ap++;
                            int p4 = (pC[j+1] >0);
                            if(p3==0 && p4==1)
                                ap++;
                            int p5 = (pD[j+1] >0);
                            if(p4==0 && p5==1)
                                ap++;
                            int p6 = (pD[j] >0);
                            if(p5==0 && p6==1)
                                ap++;
                            int p7 = (pD[j-1] >0);
                            if(p6==0 && p7==1)
                                ap++;
                            int p8 = (pC[j-1] >0);
                            if(p7==0 && p8==1)
                                ap++;
                            int p9 = (pU[j-1] >0);
                            if(p8==0 && p9==1)
                                ap++;
                            if(p9==0 && p2==1)
                                ap++;
                            if((p2+p3+p4+p5+p6+p7+p8+p9)>1 && (p2+p3+p4+p5+p6+p7+p8+p9)<7){
                                if(ap==1){
                                    if((p2*p4*p6==0)&&(p4*p6*p8==0)){                           
                                        dst.ptr<uchar>(i)[j]=0;
                                        isFinished =TRUE;                            
                                    }
                                }
                            }                    
                        }
     
                    } //扫描过程一 结束
                    dst.copyTo(tmpImg); 
                    //扫描过程二 开始
                    for(i=1; i<height;  i++){
                        pU = tmpImg.ptr<uchar>(i-1);
                        pC = tmpImg.ptr<uchar>(i);
                        pD = tmpImg.ptr<uchar>(i+1);
                        for(int j=1; j<widthj++){
                            if(pC[j] > 0){
                                int ap=0;
                                int p2 = (pU[j] >0);
                                int p3 = (pU[j+1] >0);
                                if (p2==0 && p3==1)
                                    ap++;
                                int p4 = (pC[j+1] >0);
                                if(p3==0 && p4==1)
                                    ap++;
                                int p5 = (pD[j+1] >0);
                                if(p4==0 && p5==1)
                                    ap++;
                                int p6 = (pD[j] >0);
                                if(p5==0 && p6==1)
                                    ap++;
                                int p7 = (pD[j-1] >0);
                                if(p6==0 && p7==1)
                                    ap++;
                                int p8 = (pC[j-1] >0);
                                if(p7==0 && p8==1)
                                    ap++;
                                int p9 = (pU[j-1] >0);
                                if(p8==0 && p9==1)
                                    ap++;
                                if(p9==0 && p2==1)
                                    ap++;
                                if((p2+p3+p4+p5+p6+p7+p8+p9)>1 && (p2+p3+p4+p5+p6+p7+p8+p9)<7){
                                    if(ap==1){
                                        if((p2*p4*p8==0)&&(p2*p6*p8==0)){                           
                                            dst.ptr<uchar>(i)[j]=0;
                                            isFinished =TRUE;                            
                                        }
                                    }
                                }                    
                            }
                        }
                    } //一次 先行后列扫描完成          
                    //如果在扫描过程中没有删除点,则提前退出
                    if(isFinished ==FALSE)
                        break
                }
            }
        }
    // end of thin
     
    全部代码:
    #include "stdafx.h"
    #include <iostream>
    #include <vector>
    #include "GOCVHelper.h"
     
    using namespace cv;
    using namespace std;
    using namespace GO;
     
    int main()
    {
        Mat src = imread("E:/sandbox/cross/1.bmp",0);
        Mat srcClone = src.clone();
        Mat srcBoard(src.size(),CV_8U,Scalar::all(0));
        //阈值处理
        threshold(src,src,100,255,THRESH_BINARY);
        //形态学去噪音
        Mat element = getStructuringElement(MORPH_RECT,Size(5,5));
        morphologyEx(src,src,CV_MOP_OPEN,element);
        //二值图像细化处理
        GO::thin(src,src);
        //遍历图像,这里我在遍历的时候缩了一个像素
        vector<PointvecPoints;
        for(int i=1;i<src.rows - 1;i++){     
            for(int j=1;j<src.cols - 1;j++){       
                if ( src.at<uchar>(i,j) == 255) //首先该像素要有数据
                {    
                    if (src.at<uchar>(i-1,j) == 255 && src.at<uchar>(i+1,j) == 255 && src.at<uchar>(i,j-1) == 255 && src.at<uchar>(i,j+1)==255)
                    {
                        vecPoints.push_back(Point(j,i));
                    }
                }
                     
            }
        }
        //在底图上进行绘制
        cvtColor(srcClone,srcClone,COLOR_GRAY2BGR);
        for (int i = 0;i<vecPoints.size();i++)
        {
            circle(srcClone,vecPoints[i],10,Scalar(0,0,255),-1);
            circle(srcBoard,vecPoints[i],1,Scalar(255),-1);
        }
        //对得到的有限的点进行补全和排序
        vector<intvup;
        vector<intvdown;
        projection2(srcBoard,vup,vdown,1);
     
        waitKey();
        return 0;
    }
     





  • 相关阅读:
    MVC学习
    Net开源网络爬虫
    js调用wcf 的SOA
    Redis 上实现的分布式锁
    dojo/request
    Python,PyCharm
    如何解决卸载McAfee时出现“处于托管模式时无法删除”问题(转)
    糗事⊙︿⊙
    Oracle exp,imp
    java 生产者消费者问题 并发问题的解决(转)
  • 原文地址:https://www.cnblogs.com/jsxyhelu/p/10295373.html
Copyright © 2011-2022 走看看