天天看點

選擇輪廓(select_shape)

選擇輪廓(select_shape)

    Halcon是一款運用廣泛的圖像識别和處理軟體。在膚淺的接觸中,它的輪廓選擇算子(select_shape)給予我很深的印象。結果是往往幾行代碼就能夠産生很好的效果:

      比如要得到這樣的結果

選擇輪廓(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;

    { 

        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++)

        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;

vector<VP> selectShapeCircularity(Mat src,Mat& draw,vector<VP> contours,float minvalue,float maxvalue)

        float fcompare = calculateCircularity(contours[i]);

        if (fcompare >=minvalue && fcompare <=maxvalue)

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();

結果如下,這段代碼中還有一個問題,就是計算輪廓圓的性質的方法,我這裡采用的是自己想出來的方法,似乎不是很完善,需要進一步找到資料才修正。

選擇輪廓(select_shape)
來自為知筆記(Wiz)

目前方向:圖像拼接融合、圖像識别

聯系方式:[email protected]

繼續閱讀