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();
    }
    结果如下,这段代码中还有一个问题,就是计算轮廓圆的性质的方法,我这里采用的是自己想出来的方法,似乎不是很完善,需要进一步找到资料才修正。
     
           
     
     





  • 相关阅读:
    BCTF赛后
    有道前端面试总结
    来更新一篇blog吧
    好久没更新了,开学新气象
    leetcode--N-Queens II
    leetcode--N-Queens
    leetcode--Scramble String
    leetcode--Maximal Rectangle
    leetcode--Distinct Subsequences
    leetcode--Sudoku Solver
  • 原文地址:https://www.cnblogs.com/jsxyhelu/p/4650151.html
Copyright © 2011-2022 走看看