如何用C++(OpenCV)移除像素和小于阈值的图像连通组件?
Got it, let's walk through how to replicate your Python OpenCV functionality in C++ step by step. This implementation will mirror your workflow: binarization, connected component detection, and removing components that fall below your pixel sum (or area) threshold.
In Python you used cv2.connectedComponents(), but in C++ we'll use cv::connectedComponentsWithStats—this function gives us both the label map and critical statistics (like component area or pixel sum) for each connected region, which is perfect for filtering.
Below is a full, commented code example. I'll cover two scenarios: one where you want to filter by component area (equivalent to pixel count in a binary image) and another where you filter by the sum of pixel values (for grayscale/color images).
Scenario 1: Filter by Component Area (Binary Image Pixel Count)
This matches your original Python use case where "pixel sum" refers to the number of foreground pixels in the binary image:
#include <opencv2/opencv.hpp> #include <iostream> using namespace cv; using namespace std; int main() { // Load input image (grayscale for simplicity) Mat src = imread("input_image.png", IMREAD_GRAYSCALE); if (src.empty()) { cerr << "Oops, couldn't load the image—check the file path!" << endl; return -1; } // Step 1: Binarize the image (using Otsu's auto-threshold; adjust as needed) Mat binary; threshold(src, binary, 0, 255, THRESH_BINARY | THRESH_OTSU); // Step 2: Get connected components with stats (8-connectivity, same as Python's connectivity=8) Mat labels, stats, centroids; int num_components = connectedComponentsWithStats(binary, labels, stats, centroids, 8, CV_32S); // Set your threshold (e.g., remove components smaller than 10 pixels) const int area_threshold = 10; // Step 3: Create output image and remove small components Mat output = src.clone(); for (int i = 1; i < num_components; ++i) { // Extract the area of the current component int component_area = stats.at<int>(i, CC_STAT_AREA); if (component_area < area_threshold) { // Set all pixels in this component to background (black, adjust if needed) output.setTo(0, labels == i); } } // Visualize results imshow("Original Image", src); imshow("Binary Image", binary); imshow("Output (Small Components Removed)", output); waitKey(0); // Save the result imwrite("output_image.png", output); return 0; }
Scenario 2: Filter by Sum of Pixel Values (Grayscale/Color Images)
If "pixel sum" refers to the total of all pixel values in the component (not just count), use this approach to calculate the sum explicitly:
#include <opencv2/opencv.hpp> #include <iostream> #include <vector> using namespace cv; using namespace std; int main() { Mat src = imread("input_image.png", IMREAD_GRAYSCALE); if (src.empty()) { cerr << "Failed to load image!" << endl; return -1; } // Binarize (or skip if you're working directly with grayscale) Mat binary; threshold(src, binary, 0, 255, THRESH_BINARY | THRESH_OTSU); // Get connected components Mat labels, stats, centroids; int num_components = connectedComponentsWithStats(binary, labels, stats, centroids, 8, CV_32S); // Calculate pixel sum for each component vector<int> component_pixel_sum(num_components, 0); for (int y = 0; y < labels.rows; ++y) { for (int x = 0; x < labels.cols; ++x) { int label = labels.at<int>(y, x); if (label != 0) { // Skip background component_pixel_sum[label] += src.at<uchar>(y, x); } } } // Set your sum threshold (e.g., 10) const int sum_threshold = 10; // Remove components below the threshold Mat output = src.clone(); for (int i = 1; i < num_components; ++i) { if (component_pixel_sum[i] < sum_threshold) { output.setTo(0, labels == i); } } // Display and save imshow("Original", src); imshow("Output", output); waitKey(0); imwrite("output_sum_filtered.png", output); return 0; }
- Connectivity: The
8parameter inconnectedComponentsWithStatsensures we use 8-connectivity, just like your Python example. - Stats Matrix: The
statsmatrix stores data like component area (CC_STAT_AREA), bounding box coordinates, etc.—you can explore other fields if needed for more advanced filtering. - Color Image Adjustments: If working with color images, modify the pixel sum calculation to iterate over each channel (e.g.,
src.at<Vec3b>(y,x)[0]for blue) and sum values across channels.
内容的提问来源于stack exchange,提问作者Saania

