2016-01-20 31 views
5

wejścia obrazu:Tworzenie prostokąt w blob za pomocą OpenCV

obrazu wyjściowego:

Mam kilka Barwne plamy w obrazie i próbuję tworzyć prostokątów (lub kwadraty - co wydaje się dużo łatwiejsze) wewnątrz największej kropli każdego koloru. Znalazłem the answer to how to create a rectangle that bounds a single largest blob, ale nie jestem pewien, jak znaleźć kwadrat, który po prostu pasuje do obszaru typu blob. Nie musi być największy, po prostu musi być większy niż pewien obszar, w przeciwnym razie po prostu go nie uwzględnię. Widziałem także pracę wykonaną na wielokątach, ale nic z amorficznych kształtów.

+0

Jeśli podasz non skompresowany obraz, wyślę na moją odpowiedź również wyniki na obrazie. – Miki

Odpowiedz

0

Możesz użyć this code, aby zlokalizować największy kwadrat lub prostokąt wpisany w dowolny kształt. Chociaż jest to MATLAB zamiast C++/OpenCV, możesz łatwo zmienić jego kod źródłowy, aby pasował do twoich potrzeb.

Aby zlokalizować największy prostokąt wpisany w wypukłe wielokąty, należy sprawdzić kod here.

1

W przypadku pojedynczego blobu problem można sformułować jako: find the largest rectangle containing only zeros in a matrix.

Aby znaleźć największy prostokąt zorientowany na osie wewnątrz obiektu typu blob, można skorzystać z funkcji findMinRect w my other answer. Kod jest portowaniem w C++ oryginału w Pythonie z here.


Następnie drugim problemem jest znalezienie wszystkich obiektów BLOB o tym samym kolorze. Jest to nieco skomplikowane, ponieważ obraz jest w formacie JPEG, a kompresja tworzy wiele sztucznych kolorów w pobliżu krawędzi. Stworzyłem więc obraz png (pokazany poniżej), aby pokazać, że działa algorytm. Od Ciebie zależy dostarczenie obrazu bez artefaktów kompresji.

Następnie wystarczy utworzyć maskę dla każdego koloru, znaleźć połączone elementy dla każdego obiektu typu blob w tej masce i obliczyć minimalny prostokąt dla każdego obiektu typu blob.

obraz początkowa:

enter image description here

Tu pokazać prostokąty, znalezione dla każdego blob, podzielonych według kolorów. Następnie możesz wziąć tylko te prostokąty, których potrzebujesz, albo maksymalny prostokąt dla każdego koloru, albo prostokąt dla największej kropelki dla każdego koloru.

Wynik:

enter image description here

Oto kod:

#include <opencv2/opencv.hpp> 
#include <algorithm> 
#include <set> 
using namespace std; 
using namespace cv; 

// https://stackoverflow.com/a/30418912/5008845 
Rect findMinRect(const Mat1b& src) 
{ 
    Mat1f W(src.rows, src.cols, float(0)); 
    Mat1f H(src.rows, src.cols, float(0)); 

    Rect maxRect(0, 0, 0, 0); 
    float maxArea = 0.f; 

    for (int r = 0; r < src.rows; ++r) 
    { 
     for (int c = 0; c < src.cols; ++c) 
     { 
      if (src(r, c) == 0) 
      { 
       H(r, c) = 1.f + ((r>0) ? H(r - 1, c) : 0); 
       W(r, c) = 1.f + ((c>0) ? W(r, c - 1) : 0); 
      } 

      float minw = W(r, c); 
      for (int h = 0; h < H(r, c); ++h) 
      { 
       minw = min(minw, W(r - h, c)); 
       float area = (h + 1) * minw; 
       if (area > maxArea) 
       { 
        maxArea = area; 
        maxRect = Rect(Point(c - minw + 1, r - h), Point(c + 1, r + 1)); 
       } 
      } 
     } 
    } 

    return maxRect; 
} 


struct lessVec3b 
{ 
    bool operator()(const Vec3b& lhs, const Vec3b& rhs) { 
     return (lhs[0] != rhs[0]) ? (lhs[0] < rhs[0]) : ((lhs[1] != rhs[1]) ? (lhs[1] < rhs[1]) : (lhs[2] < rhs[2])); 
    } 
}; 

int main() 
{ 
    // Load image 
    Mat3b img = imread("path_to_image"); 

    // Find unique colors 
    set<Vec3b, lessVec3b> s(img.begin(), img.end()); 

    // Divide planes of original image 
    vector<Mat1b> planes; 
    split(img, planes); 
    for (auto color : s) 
    { 
     // Create a mask with only pixels of the given color 
     Mat1b mask(img.rows, img.cols, uchar(255)); 
     for (int i = 0; i < 3; ++i) 
     { 
      mask &= (planes[i] == color[i]); 
     } 

     // Find blobs 
     vector<vector<Point>> contours; 
     findContours(mask, contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE); 

     for (int i = 0; i < contours.size(); ++i) 
     { 
      // Create a mask for each single blob 
      Mat1b maskSingleContour(img.rows, img.cols, uchar(0)); 
      drawContours(maskSingleContour, contours, i, Scalar(255), CV_FILLED); 

      // Find minimum rect for each blob 
      Rect box = findMinRect(~maskSingleContour); 

      // Draw rect 
      Scalar rectColor(color[1], color[2], color[0]); 
      rectangle(img, box, rectColor, 2); 
     } 
    } 

    imshow("Result", img); 
    waitKey(); 

    return 0; 
} 
Powiązane problemy