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