以下是一个可能的解决方案:

#include <iostream>
#include <vector>
#include <opencv2/opencv.hpp>

using namespace std;
using namespace cv;

const int THRESHOLD = 128; // 阈值
const int DISTANCE = 50; // 边界距离
const int MIN_AREA = 10; // 最小面积

int main() {
    Mat src = imread("image.png", IMREAD_GRAYSCALE); // 读取二值化图像
    if (src.empty()) {
        cerr << "Failed to read image!" << endl;
        return -1;
    }

    // 创建一个与原图像大小相同的标记图像
    Mat labels = Mat::zeros(src.size(), CV_32SC1);

    // 标记所有像素值大于阈值的像素
    int label_count = 1;
    for (int y = 0; y < src.rows; y++) {
        for (int x = 0; x < src.cols; x++) {
            if (src.at<uchar>(y, x) > THRESHOLD) {
                labels.at<int>(y, x) = label_count;
                label_count++;
            }
        }
    }

    // 统计每个标记的像素数量和边界矩形
    vector<int> label_areas(label_count, 0);
    vector<Rect> label_rects(label_count, Rect(src.cols, src.rows, 0, 0));
    for (int y = 0; y < src.rows; y++) {
        for (int x = 0; x < src.cols; x++) {
            int label = labels.at<int>(y, x);
            if (label > 0) {
                label_areas[label]++;
                label_rects[label].x = min(label_rects[label].x, x);
                label_rects[label].y = min(label_rects[label].y, y);
                label_rects[label].width = max(label_rects[label].width, x - label_rects[label].x);
                label_rects[label].height = max(label_rects[label].height, y - label_rects[label].y);
            }
        }
    }

    // 过滤面积小于最小面积的标记
    for (int i = 1; i < label_count; i++) {
        if (label_areas[i] < MIN_AREA) {
            for (int y = label_rects[i].y; y < label_rects[i].y + label_rects[i].height; y++) {
                for (int x = label_rects[i].x; x < label_rects[i].x + label_rects[i].width; x++) {
                    if (labels.at<int>(y, x) == i) {
                        labels.at<int>(y, x) = 0;
                    }
                }
            }
        }
    }

    // 过滤距离边界50个像素以内的标记
    for (int y = 0; y < src.rows; y++) {
        for (int x = 0; x < src.cols; x++) {
            int label = labels.at<int>(y, x);
            if (label > 0) {
                int distance = min(min(x, y), min(src.cols - x - 1, src.rows - y - 1));
                if (distance < DISTANCE) {
                    labels.at<int>(y, x) = 0;
                }
            }
        }
    }

    // 创建一个与原图像大小相同的输出图像
    Mat dst = Mat::zeros(src.size(), CV_8UC1);

    // 将剩余的标记转换为白色像素
    for (int y = 0; y < src.rows; y++) {
        for (int x = 0; x < src.cols; x++) {
            if (labels.at<int>(y, x) > 0) {
                dst.at<uchar>(y, x) = 255;
            }
        }
    }

    // 显示输出图像
    imshow("Output", dst);
    waitKey(0);

    return 0;
}

该代码首先读取二值化图像,然后使用阈值分割将像素值大于阈值的像素标记为不同的标记。接下来,它统计每个标记的像素数量和边界矩形,并过滤面积小于最小面积的标记。然后,它过滤距离边界50个像素以内的标记,并将剩余的标记转换为白色像素。最后,它显示输出图像

在有一张二值化图像是目标阈值分割后的特征图要求将距离图像四个边界50个像素的以内的特征图中面积小于10的特征点过滤掉其他不动要求使用指针不使用findContours要求运行时间和算法复杂度最小的完整C++代码

原文地址: https://www.cveoy.top/t/topic/dpIz 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录