2016-01-20 25 views
5

Girdi Resmi kullanarak:oluşturma dikdörtgen OpenCV

Çıktı Image:

Bir görüntüde birkaç renkli lekeler var ve dikdörtgen oluşturmak için çalışıyorum Her rengin en büyük bloğu içinde (veya çok daha kolay görünen kareler). Ben the answer to how to create a rectangle that bounds a single largest blob buldum, ama sadece bir blob içine uygun bir kare bulmak için nasıl emin değilim. En büyüğü olmak zorunda değil, sadece belirli bir alandan daha büyük olmalı, aksi takdirde içermeyeceğim. Ayrıca çokgenler üzerinde yapılmış bazı işler gördüm, ama şekilsiz şekiller için hiçbir şey yapmadım.

+0

olmayan bir sıkıştırılmış görüntü sağlarsanız, ben cevap Resminiz üzerinde de sonuçları içine göndeririz. – Miki

cevap

0

Rasgele şeklin içine yazılan en büyük kareyi veya dikdörtgeni bulmak için this code kullanabilirsiniz. C++/OpenCV yerine MATLAB olmasına rağmen, kaynak kodunu ihtiyaçlarınıza göre kolayca değiştirebilirsiniz.

Dışbükey çokgenler içine kaydedilmiş en büyük dikdörtgenin yerini bulmak için, here (kodlu) öğesini işaretleyin.

1

Tek bir blob için sorun şu şekilde formüle edilebilir: find the largest rectangle containing only zeros in a matrix.

Blob içindeki en büyük eksen yönelimli dikdörtgeni bulmak için, my other answer numaralı telefona findMinRect işlevine başvurabilirsiniz. Kod, here'dan Python'daki orijinalin C++'ndeki bir porttur.


Ardından, ikinci sorun aynı renkteki tüm lekeleri bulmaktır. Bu biraz zordur, çünkü görüntünüz jpeg ve sıkıştırma, kenarlarına yakın çok yapay renkler oluşturur. Bu yüzden sadece algoritmanın çalıştığını göstermek için bir png görüntüsü (aşağıda gösterilmiştir) oluşturdum. Sıkıştırma eserler olmadan bir görüntü sağlamak size kalmıştır.

Daha sonra, her bir renk için bir maske oluşturmanız, bu maskedeki her blob için bağlı bileşenleri bulmanız ve her blob için minimum dikdörtgeni hesaplamanız yeterlidir.

İlk resim: İşte

enter image description here

Ben renk bölünmesiyle her damla için bulunan rects göstermektedir. Ardından, yalnızca ihtiyacınız olan dikdörtgenleri, her bir renk için maksimum dikdörtgeni veya her bir renk için en büyük bloğun dikdörtgenini alabilirsiniz.

Sonuç:

İşte kodu

enter image description here

:

#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; 
}