Just a Computer Graphics Studio & My Life

有時候我們想找影像中某個物體,找到後要把它給標記出來,然後做後續處理,可以怎麼做呢?

OpenCV 尋找輪廓 Find Contours

我特地加入非純色的愛心

多虧OpenCV有提供現成的函式,就能輕易地找出物體的輪廓

接下來會使用到幾個內建函式:

  • findContours :- Find contours in the binary image.
  • drawContours :- Draw filled contour or outline of contour.
  • boundingRect :- Calculate a bounding rectangle for a contour.
  • contourArea :- Calculate area for a specific contour.
/**
 Theme: Find Contours
 IDE: Xcode 7
 Language: C++
 Date: 105/03/28
 Author: HappyMan
 Blog: https://cg2010studio.wordpress.com/
 */
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>

using namespace cv;
using namespace std;
int main(int argc, char** argv)
{
    int largest_area = 0;
    int largest_contour_index = 0;
    Rect bounding_rect;
    
    Mat src = imread("shape.jpg"); // Load source image
    Mat thr(src.rows, src.cols, CV_8UC1);
    Mat dst(src.rows, src.cols, CV_8UC3, Scalar::all(0));
    cvtColor(src, thr, CV_BGR2GRAY); // Convert to gray
    threshold(thr, thr, 25, 255, THRESH_BINARY); // Threshold the gray
    
    vector<vector<Point>> contours; // Vector for storing contour
    vector<Vec4i> hierarchy;
    
    findContours(thr, contours, hierarchy, CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE); // Find the contours in the image

    Scalar color(0,0,255);
    
    for(int i = 0; i < contours.size(); i++) // Iterate through each contour
    {
        double a = contourArea(contours[i], false); // Find the area of contour
        if(a > largest_area){
            largest_area = a;
            largest_contour_index = i; // Store the index of largest contour
            bounding_rect = boundingRect(contours[i]); // Find the bounding rectangle for biggest contour
        }
        
    }
    for(int i = 0; i < contours.size(); i++) // Iterate through each contour
    {
        if (i != largest_contour_index) {
            drawContours(dst, contours, i, color, CV_FILLED, 8, hierarchy);
        }
    }
    
    Scalar color2(255,0,0);
    drawContours(dst, contours,largest_contour_index, color2, 5, 8, hierarchy); // Draw the largest contour using previously stored index.
    
    rectangle(src, bounding_rect, Scalar(0,255,0), 1, 8, 0);
    imshow("Happy Thread", thr);
    imshow("Happy Source", src);
    imshow("Happy Largest Contour", dst);
    
    // Wait for a keystroke in the window
    waitKey(0);
    
    return 0;
}

執行後跳出三個影像:

OpenCV 尋找輪廓 Find Contours4

灰階化後設閾值找到的輪廓

OpenCV 尋找輪廓 Find Contours2

將最大輪廓給框住

OpenCV 尋找輪廓 Find Contours3

最大輪廓以藍色畫非填滿,其它輪廓以紅色畫填滿

我特地設中斷點檢視最大輪廓(愛心)的座標點,index = 4總共有214個座標點:

[4] = size=214 {
[0] = (x = 687, y = 113)
[1] = (x = 686, y = 114)
[2] = (x = 680, y = 114)
[3] = (x = 679, y = 115)
[4] = (x = 677, y = 115)
[5] = (x = 676, y = 116)
[6] = (x = 674, y = 116)
[7] = (x = 673, y = 117)
[8] = (x = 671, y = 117)
[9] = (x = 670, y = 118)
[10] = (x = 669, y = 118)
[11] = (x = 667, y = 120)
[12] = (x = 666, y = 120)
[13] = (x = 664, y = 122)
[14] = (x = 663, y = 122)
[15] = (x = 655, y = 130)
[16] = (x = 655, y = 131)
[17] = (x = 653, y = 133)
[18] = (x = 653, y = 134)
[19] = (x = 651, y = 136)
[20] = (x = 651, y = 137)
[21] = (x = 650, y = 138)
[22] = (x = 650, y = 139)
[23] = (x = 649, y = 140)
[24] = (x = 649, y = 141)
[25] = (x = 648, y = 142)
[26] = (x = 648, y = 143)
[27] = (x = 647, y = 144)
[28] = (x = 647, y = 146)
[29] = (x = 646, y = 147)
[30] = (x = 646, y = 150)
[31] = (x = 645, y = 151)
[32] = (x = 645, y = 153)
[33] = (x = 644, y = 154)
[34] = (x = 644, y = 171)
[35] = (x = 645, y = 172)
[36] = (x = 645, y = 175)
[37] = (x = 646, y = 176)
[38] = (x = 646, y = 179)
[39] = (x = 647, y = 180)
[40] = (x = 647, y = 182)
[41] = (x = 648, y = 183)
[42] = (x = 648, y = 184)
[43] = (x = 649, y = 185)
[44] = (x = 649, y = 187)
[45] = (x = 650, y = 188)
[46] = (x = 650, y = 189)
[47] = (x = 651, y = 190)
[48] = (x = 651, y = 191)
[49] = (x = 652, y = 192)
[50] = (x = 652, y = 193)
[51] = (x = 654, y = 195)
[52] = (x = 654, y = 196)
[53] = (x = 655, y = 197)
[54] = (x = 655, y = 198)
[55] = (x = 657, y = 200)
[56] = (x = 657, y = 201)
[57] = (x = 660, y = 204)
[58] = (x = 660, y = 205)
[59] = (x = 664, y = 209)
[60] = (x = 664, y = 210)
[61] = (x = 684, y = 230)
[62] = (x = 685, y = 230)
[63] = (x = 690, y = 235)
[64] = (x = 691, y = 235)
[65] = (x = 694, y = 238)
[66] = (x = 695, y = 238)
[67] = (x = 698, y = 241)
[68] = (x = 699, y = 241)
[69] = (x = 701, y = 243)
[70] = (x = 702, y = 243)
[71] = (x = 705, y = 246)
[72] = (x = 706, y = 246)
[73] = (x = 708, y = 248)
[74] = (x = 709, y = 248)
[75] = (x = 711, y = 250)
[76] = (x = 712, y = 250)
[77] = (x = 714, y = 252)
[78] = (x = 715, y = 252)
[79] = (x = 717, y = 254)
[80] = (x = 718, y = 254)
[81] = (x = 719, y = 255)
[82] = (x = 720, y = 255)
[83] = (x = 722, y = 257)
[84] = (x = 723, y = 257)
[85] = (x = 725, y = 259)
[86] = (x = 727, y = 259)
[87] = (x = 728, y = 258)
[88] = (x = 729, y = 258)
[89] = (x = 730, y = 257)
[90] = (x = 731, y = 257)
[91] = (x = 732, y = 256)
[92] = (x = 733, y = 256)
[93] = (x = 735, y = 254)
[94] = (x = 736, y = 254)
[95] = (x = 738, y = 252)
[96] = (x = 739, y = 252)
[97] = (x = 741, y = 250)
[98] = (x = 742, y = 250)
[99] = (x = 744, y = 248)
[100] = (x = 745, y = 248)
[101] = (x = 747, y = 246)
[102] = (x = 748, y = 246)
[103] = (x = 750, y = 244)
[104] = (x = 751, y = 244)
[105] = (x = 754, y = 241)
[106] = (x = 755, y = 241)
[107] = (x = 757, y = 239)
[108] = (x = 758, y = 239)
[109] = (x = 763, y = 234)
[110] = (x = 764, y = 234)
[111] = (x = 769, y = 229)
[112] = (x = 770, y = 229)
[113] = (x = 790, y = 209)
[114] = (x = 790, y = 208)
[115] = (x = 794, y = 204)
[116] = (x = 794, y = 203)
[117] = (x = 795, y = 202)
[118] = (x = 795, y = 201)
[119] = (x = 798, y = 198)
[120] = (x = 798, y = 197)
[121] = (x = 799, y = 196)
[122] = (x = 799, y = 195)
[123] = (x = 801, y = 193)
[124] = (x = 801, y = 192)
[125] = (x = 802, y = 191)
[126] = (x = 802, y = 190)
[127] = (x = 803, y = 189)
[128] = (x = 803, y = 188)
[129] = (x = 804, y = 187)
[130] = (x = 804, y = 185)
[131] = (x = 805, y = 184)
[132] = (x = 805, y = 183)
[133] = (x = 806, y = 182)
[134] = (x = 806, y = 180)
[135] = (x = 807, y = 179)
[136] = (x = 807, y = 176)
[137] = (x = 808, y = 175)
[138] = (x = 808, y = 172)
[139] = (x = 809, y = 171)
[140] = (x = 809, y = 154)
[141] = (x = 808, y = 153)
[142] = (x = 808, y = 150)
[143] = (x = 807, y = 149)
[144] = (x = 807, y = 147)
[145] = (x = 806, y = 146)
[146] = (x = 806, y = 144)
[147] = (x = 805, y = 143)
[148] = (x = 805, y = 142)
[149] = (x = 804, y = 141)
[150] = (x = 804, y = 140)
[151] = (x = 803, y = 139)
[152] = (x = 803, y = 138)
[153] = (x = 802, y = 137)
[154] = (x = 802, y = 136)
[155] = (x = 801, y = 135)
[156] = (x = 801, y = 134)
[157] = (x = 798, y = 131)
[158] = (x = 798, y = 130)
[159] = (x = 789, y = 121)
[160] = (x = 788, y = 121)
[161] = (x = 786, y = 119)
[162] = (x = 785, y = 119)
[163] = (x = 784, y = 118)
[164] = (x = 783, y = 118)
[165] = (x = 782, y = 117)
[166] = (x = 780, y = 117)
[167] = (x = 779, y = 116)
[168] = (x = 778, y = 116)
[169] = (x = 777, y = 115)
[170] = (x = 774, y = 115)
[171] = (x = 773, y = 114)
[172] = (x = 766, y = 114)
[173] = (x = 765, y = 113)
[174] = (x = 759, y = 113)
[175] = (x = 758, y = 114)
[176] = (x = 752, y = 114)
[177] = (x = 751, y = 115)
[178] = (x = 748, y = 115)
[179] = (x = 747, y = 116)
[180] = (x = 745, y = 116)
[181] = (x = 744, y = 117)
[182] = (x = 743, y = 117)
[183] = (x = 742, y = 118)
[184] = (x = 740, y = 118)
[185] = (x = 739, y = 119)
[186] = (x = 738, y = 119)
[187] = (x = 737, y = 120)
[188] = (x = 736, y = 120)
[189] = (x = 734, y = 122)
[190] = (x = 733, y = 122)
[191] = (x = 732, y = 123)
[192] = (x = 731, y = 123)
[193] = (x = 727, y = 127)
[194] = (x = 726, y = 127)
[195] = (x = 722, y = 123)
[196] = (x = 721, y = 123)
[197] = (x = 719, y = 121)
[198] = (x = 718, y = 121)
[199] = (x = 717, y = 120)
[200] = (x = 716, y = 120)
[201] = (x = 715, y = 119)
[202] = (x = 714, y = 119)
[203] = (x = 713, y = 118)
[204] = (x = 712, y = 118)
[205] = (x = 711, y = 117)
[206] = (x = 709, y = 117)
[207] = (x = 708, y = 116)
[208] = (x = 706, y = 116)
[209] = (x = 705, y = 115)
[210] = (x = 702, y = 115)
[211] = (x = 701, y = 114)
[212] = (x = 696, y = 114)
[213] = (x = 695, y = 113)
}

找到之後就可以好好處理它囉~

參考:OpenCV Find Biggest Contour Using C++

Advertisements

Comments on: "[OpenCV] 尋找輪廓 (Find Contours)" (5)

  1. 請問我想分析目標輪廓內的顏色的分布,我有辦法找到那些點的位置嗎?

    喜歡

  2. 你真的很利害 我在找什麼資料 都常找到您。 加油

    Liked by 1 person

  3. 請問你怎麼印出輪廓座標點 和總點數的

    喜歡

發表留言

在下方填入你的資料或按右方圖示以社群網站登入:

WordPress.com Logo

您的留言將使用 WordPress.com 帳號。 登出 / 變更 )

Twitter picture

您的留言將使用 Twitter 帳號。 登出 / 變更 )

Facebook照片

您的留言將使用 Facebook 帳號。 登出 / 變更 )

Google+ photo

您的留言將使用 Google+ 帳號。 登出 / 變更 )

連結到 %s

標籤雲

%d 位部落客按了讚: