For one blob, the problem can be formulated as: find the largest rectangle containing only zeros in the matrix .
To find the largest axis-oriented rectangle inside the blob, you can refer to the findMinRect function in my other answer . Code is a port in C ++ of source to Python from here .
Then the second problem is to find all the drops with the same color. This is a little tricky because your image is jpeg, and compression creates a lot of artificial colors near the borders. So I created a png image (shown below) to show that the algorithm works. This is for you to provide an image without compression artifacts.
Then you just need to create a mask for each color, find the related components for each blob in this mask and calculate the minimum rectangle for each block.
Original Image:

Here I show the rectangles found for each blob, separated by color. Then you can use only the rectangles you need, either the maximum rectangle for each color, or the rectangle for the largest blob for each color.
Result:

Here is the code:
#include <opencv2/opencv.hpp> #include <algorithm> #include <set> using namespace std; using namespace cv; // /questions/89541/find-largest-rectangle-containing-only-zeros-in-an-nn-binary-matrix/581455#581455 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; }