I want to group these white pixels that are closer to each other and draw a rectangle around them in OpenCV using C++.
Original Image:
You can count integral in each row and column. Then search for places where this integral is continuously growing. Here you can also add some moving average to exclude noise etc. Then this places means that here is more white than in other parts. Now you can use rectangle function from openCV to draw rectangle around this area (http://docs.opencv.org/2.4/modules/core/doc/drawing_functions.html#rectangle).
You can group white pixels according to a given predicate using partition. In this case, your predicate could be: group all white pixels that are within a given euclidean distance.
You can then compute the bounding boxes for each group, keep the largest box (in RED below), and eventually enlarge it (in GREEN below):
Code:
#include <opencv2\opencv.hpp>
#include <vector>
#include <algorithm>
using namespace std;
using namespace cv;
int main()
{
// Load the image
Mat3b img = imread("path_to_image", IMREAD_COLOR);
// Convert to grayscale
Mat1b gray;
cvtColor(img, gray, COLOR_BGR2GRAY);
// Get binary mask (remove jpeg artifacts)
gray = gray > 200;
// Get all non black points
vector<Point> pts;
findNonZero(gray, pts);
// Define the radius tolerance
int th_distance = 50; // radius tolerance
// Apply partition
// All pixels within the radius tolerance distance will belong to the same class (same label)
vector<int> labels;
// With lambda function (require C++11)
int th2 = th_distance * th_distance;
int n_labels = partition(pts, labels, [th2](const Point& lhs, const Point& rhs) {
return ((lhs.x - rhs.x)*(lhs.x - rhs.x) + (lhs.y - rhs.y)*(lhs.y - rhs.y)) < th2;
});
// You can save all points in the same class in a vector (one for each class), just like findContours
vector<vector<Point>> contours(n_labels);
for (int i = 0; i < pts.size(); ++i)
{
contours[labels[i]].push_back(pts[i]);
}
// Get bounding boxes
vector<Rect> boxes;
for (int i = 0; i < contours.size(); ++i)
{
Rect box = boundingRect(contours[i]);
boxes.push_back(box);
}
// Get largest bounding box
Rect largest_box = *max_element(boxes.begin(), boxes.end(), [](const Rect& lhs, const Rect& rhs) {
return lhs.area() < rhs.area();
});
// Draw largest bounding box in RED
Mat3b res = img.clone();
rectangle(res, largest_box, Scalar(0, 0, 255));
// Draw enlarged BOX in GREEN
Rect enlarged_box = largest_box + Size(20,20);
enlarged_box -= Point(10,10);
rectangle(res, enlarged_box, Scalar(0, 255, 0));
imshow("Result", res);
waitKey();
return 0;
}