查找並繪制輪廓[OpenCV 筆記XX]


好久沒有更新了,原諒自己放了個假最近又在趕進度,所以。。。更新的內容是很靠后的第八章,因為最近工作要用就先跳了,后面會更新筆記編號。。。加油加油!

 

在二值圖像中尋找輪廓

void cv::findContours    (    InputOutputArray     image,
                        OutputArrayOfArrays     contours,
                        OutputArray     hierarchy,
                        int     mode,
                        int     method,
                        Point     offset = Point() 
                      )    
  • image: 輸入圖像,需為8位單通道圖像,圖像非0像素視為1。 可以用compare(), imrange(), threshold(), adaptivethreshold(), canny()等函數創建,注意:此函數會在提取圖像輪廓的同時修改圖像內容。
    • If mode equals to RETR_CCOMP or RETR_FLOODFILL, the input can also be a 32-bit integer image of labels (CV_32SC1).
  • contours: 檢測到的輪廓,每個輪廓存儲為一個點向量,即用point類型的vector,例如可為類型vector<vector<Point> >。
  • hierarchy: 可選的輸出向量,包含圖像的拓撲信息。 每個輪廓contours[i],
    • hierarchy[i][0] , 后一個輪廓,
    • hierarchy[i][1] , 前一個輪廓,
    • hierarchy[i][2] , 父輪廓,
    • hierarchy[i][3], 內嵌輪廓的索引編號。
    • 如果沒有對應項,hierarchy[i]中的對應項設為負數。
  • mode: 檢索模式,可選模式包括
    • RETR_EXTERNAL: 只監測最外層輪擴。hierarchy[i][2] = hierarchy[i][3] = -1
    • RETR_LIST: 提取所有輪廓,並放置在list中。檢測的輪廓不建立等級關系。
    • RETR_CCOMP: 提取所有輪廓,並將其組織為雙層結構,頂層為聯通域的外圍邊界,次層為空的內層邊界。
    • RETR_TREE: 提取所有輪廓,並重新建立網狀的輪廓結構。
  • method: 輪廓的近似辦法,包括
    • CHAIN_APPROX_NONE: 獲取每個輪廓的每個像素,相鄰兩點像素位置差不超過1,max(abs(x1-x2),abs(y1-y2)) == 1
    • CHAIN_APPROX_SIMPLE: 壓縮水平方向,垂直方向,對角線方向的元素,只保留該方向的終點坐標
    • CHAIN_APPROX_TC89_LI /CHAIN_APPROX_TC89_KCOS: 使用Teh-Chinl鏈逼近算法中的一個
      • [135] C-H Teh and Roland T. Chin. On the detection of dominant points on digital curves. Pattern Analysis and Machine Intelligence, IEEE Transactions on, 11(8):859–872, 1989.
  • offSet: 每個輪廓點的可選偏移量,默認Point(), 當ROI圖像中找出的輪廓需要在整個圖中進行分析時,可利用這個參數。

繪制輪廓

void cv::drawContours    (    InputOutputArray     image,
                        InputArrayOfArrays     contours,
                        int     contourIdx,
                        const Scalar &     color,
                        int     thickness = 1,
                        int     lineType = LINE_8,
                        InputArray     hierarchy = noArray(),
                        int     maxLevel = INT_MAX,
                        Point     offset = Point() 
                      )    
  • image: 目標圖像
  • contours: 輸入輪廓,每個輪廓存儲為一個點向量
  • contourIdx: 需要繪制的輪廓的編號,如果為負,繪制所有輪廓
  • color: 輪廓顏色
  • thickness: 輪廓線條粗細度,如果為負值(如thickness==cv_filled),繪制在輪廓內部
  • lineType: 線條類型
    • 8: 8連通線型
    • 4: 4連通線型
    • LINE_AA (OpenCV2: CV_AA): 抗鋸齒線型
  • hierarchy: 可選層次結構
  • maxLevel: 繪制輪廓的最大等級
  • offset: 可選輪廓偏移參數

事例程序1

#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <vector>

// main
int main( int argc, char** argv )
{
    // loading image
    cv::Mat srcImage = cv::imread("1.jpg", 0);
    imshow("original image", srcImage);
    
    // initialize result image
    cv::Mat dstImage = cv::Mat::zeros(srcImage.rows, srcImage.cols, CV_8UC3);
    
    // thresholding image
    srcImage = srcImage > 119;
    imshow("thresholding image", srcImage);
    
    // finding contours
    std::vector<std::vector<cv::Point> > contours;
    std::vector<cv::Vec4i> hierarchy;
    // for opencv 2
    // cv::findContours(srcImage, contours, hierarchy, CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE);
    // for opencv 3
    cv::findContours(srcImage, contours, hierarchy, cv::RETR_CCOMP, cv::CHAIN_APPROX_SIMPLE);
    
    // iterate through all levels, and draw contours in random color
    int index = 0;
    for (; index>=0; index = hierarchy[index][0]) {
        cv::Scalar color(rand()&255, rand()&255, rand()&255);
        // for opencv 2
        // cv::drawContours(dstImage, contours, index, color,  CV_FILLED, 8, hierarchy);
        // for opencv 3
        cv::drawContours(dstImage, contours, index, color,  cv::FILLED, 8, hierarchy);
        
        imshow("contours", dstImage);
        cv::waitKey(150);
    }
    cv::imwrite("result.jpg", dstImage);
    return 0;
}

1.jpg

 

result.jpg

事例程序2

#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
#include <vector>

#define WINDOW_NAME1 "original image"
#define WINDOW_NAME2 "contours"

// global variables
cv::Mat g_srcImage;
cv::Mat g_grayImage;
cv::Mat g_cannyMat_output;
int g_nThresh = 80;
int g_nThresh_max = 255;
cv::RNG g_rng(12345);
std::vector<std::vector<cv::Point> > g_vContours;
std::vector<cv::Vec4i> g_vHierarchy;

// functions
void on_ThreshChange(int, void*);

// main
int main( int argc, char** argv )
{
    // change the text color of console
    system("color 1F");
    
    // loading image
    g_srcImage = cv::imread("1.jpg", 1);
    if (!g_srcImage.data){
        std::cerr << "ERROR while loading image." << std::endl;
        return false;
    }
    
    // convert to gray-scale and blur
    cv::cvtColor(g_srcImage, g_grayImage, cv::COLOR_BGR2GRAY);
    cv::blur(g_grayImage, g_grayImage, cv::Size(3,3));
    
    // create window
    cv::namedWindow(WINDOW_NAME1, cv::WINDOW_AUTOSIZE);
    imshow(WINDOW_NAME1, g_srcImage);
    
    // create tracker bar
    cv::createTrackbar("Canny Threshold", WINDOW_NAME1, &g_nThresh, g_nThresh_max, on_ThreshChange);
    on_ThreshChange(0, 0);
    
    cv::waitKey(0);
    return 0;
}

void on_ThreshChange(int, void*)
{
    cv::Canny(g_grayImage, g_cannyMat_output, g_nThresh, g_nThresh*2, 3);
    
    cv::findContours(g_cannyMat_output, g_vContours, g_vHierarchy, cv::RETR_TREE, cv::CHAIN_APPROX_SIMPLE);
    
    cv::Mat drawing = cv::Mat::zeros(g_cannyMat_output.size(), CV_8UC3);
    for (int i = 0; i<g_vContours.size(); i++) {
        cv::Scalar color(g_rng.uniform(0, 255), g_rng.uniform(0, 255), g_rng.uniform(0, 255));
        cv::drawContours(drawing, g_vContours, i, color,  2, 8, g_vHierarchy);
    }
    imshow(WINDOW_NAME2, drawing);
}

結果圖:

 

 

 

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM