【问题标题】:Finding the most left, most right, most high and most down blue pixel with C++ and opencv使用 C++ 和 opencv 查找最左边、最右边、最高和最下方的蓝色像素
【发布时间】:2019-11-20 20:13:34
【问题描述】:

我正在尝试使用 c++ 和 opencv 编写一个代码,该代码将识别哪个蓝色像素从左、右、上和下首先出现。 我正在使用的图片是这张:

而我想收到的是这样的图片:

到目前为止,这是我的代码,我真的不明白为什么它不起作用。

    void findBluePixels(Mat& original, Point2f min_x, Point2f max_x, Point2f min_y, Point2f max_y) {
    //First I set every point to the beginning of the image
        min_x = Point(0, 0);
        max_x = Point(0, 0);
        min_y = Point(0, 0);
        max_y = Point(0, 0);
    //looking for the most left blue pixel (the blue pixel with the smallest x value)
    //we are going through every column and every row
        for (int col = 0; col < original.cols; col++) {
            for (int row = 0; row < original.rows; row++) {
    //we check for every pixel if the pixel is blue and if the column of the pixel is bigger or equal to the beginning of the image
    if (original.at<Vec3b>(row, col)[0] == 255 && 
    original.at<Vec3b>(row, col)[1] == 0 &&
 original.at<Vec3b>(row, col)[2] == 0 && col >= min_x.y) {
    //if yes we have new value for the min_x and we stop looking because we have found the most left blue pixel
        min_x = Point(row, col);
        break;
                }
            }
        }
    //looking for the most right blue pixel (the blue pixel with the biggest x value)
    //we are going through every column and every row
        for (int col = 0; col < original.cols; col++) {
            for (int row = 0; row < original.rows; row++) {
    //we check for every pixel if the pixel is blue and if the column of the pixel is bigger or equal to the beginning of the image
    if (original.at<Vec3b>(row, col)[0] == 255 && 
    original.at<Vec3b>(row, col)[1] == 0 && 
original.at<Vec3b>(row, col)[2] == 0 && col >= max_x.y) {
    //if yes we have new value for the max_x, but we don't break because we are looking for the biggest blue pixel
    //we continue to search until the end of the picture
    max_x = Point(row, col);
                }
            }
        }
    //looking for the highest blue pixel (the blue pixel with the smallest y value)
    //we are going through every row and every column
        for (int row = 0; row < original.rows; row++) {
            for (int col = 0; col < original.cols; col++) {
    //we check for every pixel if the pixel is blue and if the row of the pixel is bigger or equal to the beginning of the image
    if (original.at<Vec3b>(row, col)[0] == 255 && 
    original.at<Vec3b>(row, col)[1] == 0 &&
    original.at<Vec3b>(row, col)[2] == 0 && row >= min_y.x) {
    //if yes we have new value for the min_y and we stop looking because we have found the highest blue pixel
    min_y = Point(row, col);
    break;
                }
            }
        }
    //looking for the most down blue pixel (the blue pixel with the biggest y value)
    //we are going through every column and every row
        for (int row = 0; row < original.rows; row++) {
            for (int col = 0; col < original.cols; col++) {
    //we check for every pixel if the pixel is blue and if the row of the pixel is bigger or equal to the beginning of the image
    if (original.at<Vec3b>(row, col)[0] == 255 && 
    original.at<Vec3b>(row, col)[1] == 0 &&
    original.at<Vec3b>(row, col)[2] == 0 && row >= max_y.x) {
    //if yes we have new value for the max_y, but we don't break because we are looking for the biggest blue pixel
    //we continue to search until the end of the picture
    max_y = Point(row, col);
                }
            }
        }
    //Here I want to make green points on the pixels we have found
    circle(original, min_x, 3, Scalar(0, 255, 0), 8, LINE_AA);
    circle(original, max_x, 3, Scalar(0, 255, 0), 8, LINE_AA);
    circle(original, min_y, 3, Scalar(0, 255, 0), 8, LINE_AA);
    circle(original, max_y, 3, Scalar(0, 255, 0), 8, LINE_AA);
}

我最后收到的点是完全随机的。

如果有人可以提供帮助,我将不胜感激! :)

【问题讨论】:

  • 不知道,但你应该提取一个函数bool is_blue( const Pixel &amp;) 以使代码更易读和简洁。
  • 对不起,但你的逻辑对我来说似乎完全随机。无论如何,这就是调试器的用途,使用它来准确地找出您的程序何时何地偏离了您的期望。
  • 您没有在帖子中指定您的坐标系,这很难确定。但是col &gt;= max_x.y 将我认为是 x 坐标的列与 y 坐标进行比较。那是没有意义的。所有其他比较都存在同样的问题,您似乎混淆了 x 和 y。
  • 你的符号有问题。如果 x 从左到右,y 从上到下(或相反,w/e),col 对应于你的 x 值和row 到 y 值。如果这不是您想要的符号,那么最左边和最右边的定义是错误的。
  • min_xmax_x 的代码相同。在某处搞砸了&gt;=&lt;=

标签: c++ opencv


【解决方案1】:
  1. 您应仅在矩阵上循环一次,并在同一(内部)for 循环体中执行所有检查。

  2. 更喜欢使用名称而不是数字。例如if (original.at(row, col)[BLUE] == 255 而不是 if (original.at(row, col)[0] == 255

  3. 请仔细检查像素中的索引 0 确实保持蓝色值(不是 RGB 吗?)

  4. 逻辑问题:如果你想找到例如最小 x,你应该编码 (col

    如果 (... && col min_x = 点(行,列); 休息; }

并初始化如下:

min_x = Point(MAX_COL, 0);
max_x = Point(MIN_COL, 0);
min_y = Point(0, MAX_ROW);
max_y = Point(0, MIN_ROW);

【讨论】:

    【解决方案2】:

    正如@nivpeled 提到的,但在代码中。

    void findBluePixels(Mat& original) {
        Point min_x = Point(original.cols, original.rows);
        Point min_y = Point(original.cols, original.rows);
        Point max_x = Point(-1, -1);
        Point max_y = Point(-1, -1);
        //looking for the most left blue pixel (the blue pixel with the smallest x value)
        //we are going through every column and every row
    
        const Vec3b blueColor(255, 0, 0);
        for (int row = 0; row < original.rows; row++) {
            for (int col = 0; col < original.cols; col++) {
                if (blueColor != original.at<Vec3b>(row, col))
                    continue;
    
                if (min_x.x > col) {
                    min_x = Point(col, row);
                }
                if (max_x.x < col) {
                    max_x = Point(col, row);
                }
    
                if (min_y.y > row) {
                    min_y = Point(col, row);
                }
                if (max_y.y < row) {
                    max_y = Point(col, row);
                }
            }
        }
        //Here I want to make green points on the pixels we have found
        circle(original, min_x, 13, Scalar(0, 255, 0), 8, LINE_AA);
        circle(original, max_x, 13, Scalar(0, 255, 0), 8, LINE_AA);
        circle(original, min_y, 13, Scalar(0, 255, 0), 8, LINE_AA);
        circle(original, max_y, 13, Scalar(0, 255, 0), 8, LINE_AA);
    }
    

    还有一些建议:

    • 执行 for 循环首先为行,然后为列。如果您按顺序访问数据,计算机的工作速度会更快。示例访问序列编号:

    Faster ->
    [ 1 2 3 ] 
    [ 4 5 6 ] 
    [ 7 8 9 ] 
    Slower ->
    [ 1 4 7 ] 
    [ 2 5 8 ] 
    [ 3 6 9 ]
    

    【讨论】:

    • 非常感谢您的解决方案和提示!
    • 我会让 blueColor 成为 const 甚至是静态 constexpr。
    猜你喜欢
    • 1970-01-01
    • 2018-01-13
    • 1970-01-01
    • 1970-01-01
    • 2012-02-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-11
    相关资源
    最近更新 更多