【问题标题】:Find first red pixel and crop picture找到第一个红色像素并裁剪图片
【发布时间】:2026-02-02 14:15:01
【问题描述】:

我想用 OpenCV 找到第一个红色像素,然后剪掉它右边的图片。

此刻我写了这段代码,但运行起来很慢:

        int firstRedPixel = mat.Cols();
        int len = 0;


           for (int x = 0; x < mat.Rows(); x++)
            {
                for (int y = 0; y < mat.Cols(); y++)
                {
                    double[] rgb = mat.Get(x, y);
                    double r = rgb[0];
                    double g = rgb[1];
                    double b = rgb[2];

                    if ((r > 175) && (r > 2 * g) && (r > 2 * b))
                    {
                        if (len == 3)
                        {
                            firstRedPixel = y - len;
                            break;
                        }

                        len++;
                    }
                    else
                    {
                        len = 0;
                    }
                }
            }

有什么解决办法吗?

【问题讨论】:

标签: java c# opencv graphics tesseract


【解决方案1】:

你可以:

1) 找到红色像素(见here

2) 得到红色像素的边界框

3) 裁剪图像

代码是 C++,但它只是 OpenCV 函数,所以移植到 Java 应该不难:

#include <opencv2\opencv.hpp>

int main()
{
    cv::Mat3b img = cv::imread("path/to/img");

    // Find red pixels
    // https://*.com/a/32523532/5008845
    cv::Mat3b bgr_inv = ~img;
    cv::Mat3b hsv_inv;
    cv::cvtColor(bgr_inv, hsv_inv, cv::COLOR_BGR2HSV);

    cv::Mat1b red_mask;
    inRange(hsv_inv, cv::Scalar(90 - 10, 70, 50), cv::Scalar(90 + 10, 255, 255), red_mask); // Cyan is 90

                                                                                            // Get the rect
    std::vector<cv::Point> red_points;
    cv::findNonZero(red_mask, red_points);

    cv::Rect red_area = cv::boundingRect(red_points);

    // Show green rectangle on red area
    cv::Mat3b out = img.clone();
    cv::rectangle(out, red_area, cv::Scalar(0, 255, 0));

    // Define the non red area
    cv::Rect not_red_area;
    not_red_area.x = 0;
    not_red_area.y = 0;
    not_red_area.width = red_area.x - 1;
    not_red_area.height = img.rows;

    // Crop away red area
    cv::Mat3b result = img(not_red_area);

    return 0;
}   

【讨论】:

    【解决方案2】:

    这不是使用计算机视觉的方式。我知道这一点,因为我也是这样做的。

    实现目标的一种方法是使用模板匹配从图像中剪下的红色条,从而找到红色边框并将其剪掉。

    另一种方法是转移到 HSV 空间,过滤掉红色内容,并根据需要使用轮廓查找来定位大型红色结构。

    有很多方法可以做到这一点。但是,在像素值上循环很少是正确的方法,并且您不会以这种方式利用复杂的矢量化或算法。

    【讨论】:

    • 我想最好只训练整个序列,然后以编程方式裁剪尾部子字符串(3 个位置)。我的意思是,您所需要的只是识别数字及其顺序。
    • 我只需要识别黑色背景上的部分
    • 我还将专注于识别数字 - 再次模板匹配 可以 在这里提供帮助 - 然后只是丢失最后两位数字。