2016-01-20 13 views
5

入力画像の使用ブロブ内の四角形を作成:OpenCVの

出力イメージ:

を、私は、画像に複数の色のブロブを持っていると私は長方形を作成しようとしています(または、より簡単に見える四角形)を各色の最も大きな塊の中に入れます。私はthe answer to how to create a rectangle that bounds a single largest blobを見つけましたが、ブロブの中に単に収まる広場を見つける方法は不明です。それは最大である必要はありません、それはちょうど特定の領域よりも大きい必要がありますそれ以外の場合は私はそれを含めません。私はポリゴンで行われたいくつかの作業も見てきましたが、無定形のものは何も見つかりませんでした。

+0

あなたは非圧縮画像を提供する場合、私はあなたのイメージにも私の答えに結果を投稿します。 – Miki

答えて

0

this codeを使用すると、任意の形状に内接する最大の正方形または長方形を見つけることができます。 C++/OpenCVではなくMATLABですが、必要に応じてソースコードを簡単に変更できます。

凸多角形に内接する最大の長方形を見つけるには、here(コード付き)をチェックしてください。

1

単一ブロブの場合、問題は次のように公式化できます。find the largest rectangle containing only zeros in a matrix

ブロブの中で最大の軸指向の矩形を見つけるには、findMinRectmy other answerを参照してください。このコードは、PythonのオリジナルのC++での移植で、hereです。


次に、同じ色のすべてのブロブを見つけることです。あなたの画像がJPEGで圧縮が多くの人工的な色を境界線の近くに作成するため、これはややこしいことです。だから、アルゴリズムが動作することを示すために、pngイメージ(下に示す)を作成しました。圧縮アーチファクトのない画像を提供するのはあなた次第です。

次に、各色のマスクを作成し、このマスク内の各ブロブの接続コンポーネントを見つけ、各ブロブの最小矩形を計算するだけです。

初期画像:ここで

enter image description here

私は色で分け、各ブロブが見つかりrectsを示しました。次に、各色の最大矩形か、各色の最大矩形のいずれかの矩形だけを取り出すことができます。

結果:

ここ

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