zoukankan      html  css  js  c++  java
  • 选择轮廓(select_shape)

    选择轮廓(select_shape)
        
        Halcon是一款运用广泛的图像识别和处理软件。在肤浅的接触中,它的轮廓选择算子(select_shape)给予我很深的印象。结果是往往几行代码就能够产生很好的效果:
          比如要得到这样的结果
           只需要
    read_image (Image1, 'F:/未来项目/钢管识别/FindTube/FindTube/1.jpg')
    rgb1_to_gray (Image1, GrayImage)
    threshold (GrayImage, Regions, 43, 111)
    connection (Regions, ConnectedRegions)
    select_shape (ConnectedRegions, SelectedRegions, 'area', 'and', 150, 666)
    select_shape (SelectedRegions, SelectedRegions1, 'circularity', 'and', 0.45, 1)
          当然Halcon是在背后做了许多工作的。
          几行代码中,比较重要的是算子就是"select_shape"。这个算子的参数很多,我也就比较熟悉这两种。
          如果我想在Opencv中也要这样的结果,就需要自己动手尝试实现。实现过程中我采用了类似的函数名表示敬意。
    // selectshape.cpp : 选择轮廓
    // by: jsxyhelu(1755311380)
    #include "stdafx.h"
    #include <iostream>
    #include "opencv2/core/core.hpp"
    #include "opencv2/highgui/highgui.hpp"
    #include "opencv2/imgproc/imgproc.hpp"
    using namespace std;
    using namespace cv;
    #define  VP  vector<Point>  //用VP符号代替 vector<point>
    RNG  rng(12345    );
    //带有上下限的threshold
    void threshold2(Mat gray,Mat& thresh,int minvalue,int maxvalue)
    {
        Mat thresh1;
        Mat thresh2;
        threshold(gray,thresh1,43,255, THRESH_BINARY);
        threshold(gray,thresh2,111,255,THRESH_BINARY_INV);
        thresh = thresh1 & thresh2;
    }
    //寻找并绘制出联通区域
    vector<VP> connection2(Mat src,Mat& draw)
    {    
        draw = Mat::zeros(src.rows,src.cols,CV_8UC3);
        vector<VP>contours;    
        findContours(src,contours,CV_RETR_LIST,CV_CHAIN_APPROX_SIMPLE);
        for (int i=0;i<contours.size();i++)
        {
            Scalar  color  = Scalar(rng.uniform(0,255),rng.uniform(0,255),rng.uniform(0,255));
            drawContours(draw,contours,i,color,-1);
        }
        return contours;
    }
    //select_shape
    vector<VP>  selectShapeArea(Mat src,Mat& draw,vector<VP> contours,int minvalue,int maxvalue)
    {
        vector<VP> result_contours;
        draw = Mat::zeros(src.rows,src.cols,CV_8UC3);
        for (int i=0;i<contours.size();i++)
        { 
            int countour_area = contourArea(contours[i]);
            if (countour_area >minvalue && countour_area<maxvalue)
            {
                result_contours.push_back(contours[i]);
            }
        }
        for (int i=0;i<result_contours.size();i++)
        {
            Scalar  color  = Scalar(rng.uniform(0,255),rng.uniform(0,255),rng.uniform(0,255));
            drawContours(draw,result_contours,i,color,-1);
        }
        return result_contours;
    }
    //计算轮廓的圆的特性
    float calculateCircularity(VP contour)
    {
        Point2f center;
        float radius = 0;
        minEnclosingCircle((Mat)contour,center,radius);
        //以最小外接圆半径作为数学期望,计算轮廓上各点到圆心距离的标准差
        float fsum = 0;
        float fcompare = 0;
        for (int i=0;i<contour.size();i++)
        {   
            Point2f ptmp = contour[i];
            float fdistenct = sqrt((float)((ptmp.x - center.x)*(ptmp.x - center.x)+(ptmp.y - center.y)*(ptmp.y-center.y)));
            float fdiff = abs(fdistenct - radius);
            fsum = fsum + fdiff;
        }
        fcompare = fsum/(float)contour.size();
        return fcompare;
    }
    //select_shape
    vector<VP> selectShapeCircularity(Mat src,Mat& draw,vector<VP> contours,float minvalue,float maxvalue)
    {
        vector<VP> result_contours;
        draw = Mat::zeros(src.rows,src.cols,CV_8UC3);
        for (int i=0;i<contours.size();i++)
        {
            float fcompare = calculateCircularity(contours[i]);
            if (fcompare >=minvalue && fcompare <=maxvalue)
            {
                result_contours.push_back(contours[i]);
            }
        }
        for (int i=0;i<result_contours.size();i++)
        {
            Scalar  color  = Scalar(rng.uniform(0,255),rng.uniform(0,255),rng.uniform(0,255));
            drawContours(draw,result_contours,i,color,-1);
        }
        return result_contours;
    }
    int _tmain(int argc, _TCHAR* argv[])
    {    
        Mat src;
        Mat gray;
        Mat thresh;
        Mat draw_connection;
        Mat draw_area;
        Mat draw_circle;
        vector<VP>contours_connection;    
        vector<VP>contours_area;
        vector<VP>contours_circle;
        vector<VP>contours_tmp;
        //read_image (Image1, 'F:/未来项目/钢管识别/FindTube/FindTube/1.jpg')
        src = imread("1.jpg");
        //rgb1_to_gray (Image1, GrayImage)
        cvtColor(src,gray,COLOR_BGR2GRAY);
        //threshold (GrayImage, Regions, 43, 111)
        threshold2(gray,thresh,43,111);
        //connection (Regions, ConnectedRegions)
        contours_connection = connection2(thresh.clone(),draw_connection);
        //select_shape (ConnectedRegions, SelectedRegions, 'area', 'and', 150, 666)
        contours_area = selectShapeArea(thresh.clone(),draw_area,contours_connection,150,666);
        //select_shape (SelectedRegions, SelectedRegions1, 'circularity', 'and', 0.45, 1)
        contours_circle = selectShapeCircularity(thresh.clone(),draw_circle,contours_area,1,6);
        //显示结果
        imshow("src",src);
        imshow("thresh",thresh);
        imshow("draw_connection",draw_connection);
        imshow("draw_area",draw_area);
        imshow("draw_circle",draw_circle);
        waitKey();
    }
    结果如下,这段代码中还有一个问题,就是计算轮廓圆的性质的方法,我这里采用的是自己想出来的方法,似乎不是很完善,需要进一步找到资料才修正。
     
           
     
     





  • 相关阅读:
    windows 按时自动化任务
    Linux libusb 安装及简单使用
    Linux 交换eth0和eth1
    I.MX6 GPS JNI HAL register init hacking
    I.MX6 Android mmm convenient to use
    I.MX6 GPS Android HAL Framework 调试
    Android GPS GPSBasics project hacking
    Python windows serial
    【JAVA】别特注意,POI中getLastRowNum() 和getLastCellNum()的区别
    freemarker跳出循环
  • 原文地址:https://www.cnblogs.com/jsxyhelu/p/4650151.html
Copyright © 2011-2022 走看看