cxnet 发表于 2024-12-9 09:56:10

像素处理问题

请帮我看一下下面的C++代码问题出在哪里,检查了好几遍都没发现问题,我要实现的效果如下描述:
如果当前像素为白色,检测x轴前面第2和第3像素是否为纯黑色,如果结果为真将前面1像素设置为白色,如果前面2和3像素颜色一致且不是纯黑将前面1像素设置为前面第2像素一样的颜色,再检测后面第2和第3像素是否为纯黑色,如果结果为真,将当前像素后面1像素设置为白色,如果后面2和3像素颜色一致且不是纯黑将后面1像素设置为后面第2像素一样的颜色。同时也检测y轴上面第2和第3像素是否为纯黑色,如果结果为真将上面1像素设置为白色,如果上面2和3像素颜色一致且不是纯黑将上面1像素设置为上面第2像素一样的颜色,再检测下面第2和第3像素是否为纯黑色,如果结果为真,将当前像素下面1像素设置为白色,如果下面2和3像素颜色一致且不是纯黑将下面1像素设置为下面第2像素一样的颜色。

void processImage(Mat& img) {
        // 遍历图像的每个像素(不包括边缘像素,因为它们没有足够的邻居)
        for (int y = 2; y < img.rows - 2; ++y) {
                for (int x = 2; x < img.cols - 2; ++x) {
                        // 获取当前像素值
                        uchar currentValue = img.at<uchar>(x, y);

                        // 如果当前像素为白色(假设白色为255)
                        if (currentValue == 255) {
                                // 检测x轴前面第2和第3像素
                                int xFront2Value = img.at<uchar>(x - 2, y);
                                int xFront3Value = img.at<uchar>(x - 3, y);

                                // 检测x轴后面第2和第3像素
                                int xAfter2Value = img.at<uchar>(x + 2, y);
                                int xAfter3Value = img.at<uchar>(x + 3, y);

                                // 设置前面1像素
                                if (xFront2Value == 0 && xFront3Value == 0) {
                                        img.at<uchar>(x - 1, y) = 255;
                                }
                                else if (xFront2Value == xFront3Value && xFront2Value != 0) {
                                        img.at<uchar>(x - 1, y) = xFront2Value;
                                }
                                else if (xAfter2Value == 0 && xAfter3Value == 0) {
                                        img.at<uchar>(x + 1, y) = 255;
                                }
                                else if (xAfter2Value == xAfter3Value && xAfter2Value != 0) {
                                        img.at<uchar>(x + 1, y) = xAfter2Value;
                                }

                                // 检测y轴上面第2和第3像素
                                int yUp2Value = img.at<uchar>(x, y - 2);
                                int yUp3Value = img.at<uchar>(x, y - 3);

                                // 检测y轴下面第2和第3像素
                                int yDown2Value = img.at<uchar>(x, y + 2);
                                int yDown3Value = img.at<uchar>(x, y + 3);

                                // 设置上面1像素
                                if (yUp2Value == 0 && yUp3Value == 0) {
                                        img.at<uchar>(x, y - 1) = 255;
                                }
                                else if (yUp2Value == yUp3Value && yUp2Value != 0) {
                                        img.at<uchar>(x, y - 1) = yUp2Value;
                                }
                                else if (yDown2Value == 0 && yDown3Value == 0) {
                                        img.at<uchar>(x, y + 1) = 255;
                                }
                                else if (yDown2Value == yDown3Value && yDown2Value != 0) {
                                        img.at<uchar>(x, y + 1) = yDown2Value;
                                }

                        }
                }
        }
}

FishC 发表于 2024-12-9 10:03:14

在您的代码中,有几个问题可能导致实现没有达到预期效果。以下是您需要注意的地方:

1. **像素访问方式错误**:在OpenCV中,`img.at<uchar>(y, x)` 应该用来访问单通道(灰度图像)的像素值,而不是 `img.at(x, y)`。

2. **条件判断顺序**:对x轴和y轴的检测,您把设置像素的条件放在一个block中。如果一个条件为真,后面的条件就不会被检测。因此,您可能需要对这些条件分开处理。

以下是修正后的改进代码:

void processImage(Mat& img) {
        // 遍历图像的每个像素(不包括边缘像素,因为它们没有足够的邻居)
        for (int y = 2; y < img.rows - 2; ++y) {
                for (int x = 2; x < img.cols - 2; ++x) {
                        // 获取当前像素值
                        uchar currentValue = img.at<uchar>(y, x);

                        // 如果当前像素为白色(假设白色为255)
                        if (currentValue == 255) {
                                // 检测x轴前面第2和第3像素
                                uchar xFront2Value = img.at<uchar>(y, x - 2);
                                uchar xFront3Value = img.at<uchar>(y, x - 3);

                                // 设置前面1像素
                                if (xFront2Value == 0 && xFront3Value == 0) {
                                        img.at<uchar>(y, x - 1) = 255;
                                } else if (xFront2Value == xFront3Value && xFront2Value != 0) {
                                        img.at<uchar>(y, x - 1) = xFront2Value;
                                }

                                // 检测x轴后面第2和第3像素
                                uchar xAfter2Value = img.at<uchar>(y, x + 2);
                                uchar xAfter3Value = img.at<uchar>(y, x + 3);

                                // 设置后面1像素
                                if (xAfter2Value == 0 && xAfter3Value == 0) {
                                        img.at<uchar>(y, x + 1) = 255;
                                } else if (xAfter2Value == xAfter3Value && xAfter2Value != 0) {
                                        img.at<uchar>(y, x + 1) = xAfter2Value;
                                }

                                // 检测y轴上面第2和第3像素
                                uchar yUp2Value = img.at<uchar>(y - 2, x);
                                uchar yUp3Value = img.at<uchar>(y - 3, x);

                                // 设置上面1像素
                                if (yUp2Value == 0 && yUp3Value == 0) {
                                        img.at<uchar>(y - 1, x) = 255;
                                } else if (yUp2Value == yUp3Value && yUp2Value != 0) {
                                        img.at<uchar>(y - 1, x) = yUp2Value;
                                }

                                // 检测y轴下面第2和第3像素
                                uchar yDown2Value = img.at<uchar>(y + 2, x);
                                uchar yDown3Value = img.at<uchar>(y + 3, x);

                                // 设置下面1像素
                                if (yDown2Value == 0 && yDown3Value == 0) {
                                        img.at<uchar>(y + 1, x) = 255;
                                } else if (yDown2Value == yDown3Value && yDown2Value != 0) {
                                        img.at<uchar>(y + 1, x) = yDown2Value;
                                }
                        }
                }
        }
}

以上代码将对像素的访问方式进行了正确处理,并分隔了x轴和y轴的条件判断,以确保其独立运行。希望这样可以解决您遇到的问题。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

cxnet 发表于 2024-12-9 10:19:20

FishC 发表于 2024-12-9 10:03
在您的代码中,有几个问题可能导致实现没有达到预期效果。以下是您需要注意的地方:

1. **像素访问方式 ...

我用了这段代码后还是一样的错误,我把 下面2行后面的++y改为y+=3和x+=3就不会报错,但是处理完成的图片没有什么效果,颜色没有替换成功
for (int y = 2; y < img.rows - 2; ++y) {
                for (int x = 2; x < img.cols - 2; ++x) {

FishC 发表于 2024-12-9 10:23:23

cxnet 发表于 2024-12-09 10:19
我用了这段代码后还是一样的错误,我把 下面2行后面的 ...

您提到修改循环步进可以避免报错,但这样可能会跳过某些像素,导致处理不完整。首先,代码可能存在以下几个常见问题:

1. **图像类型和通道数**:确认图像为灰度图(单通道),因为当前代码针对单通道图像。你可以使用 `cvtColor` 将彩色图像转换为灰度图。

2. **像素值的修改**:在处理过程中,最好将结果保存到一个新图像中,以防止在同一次迭代中修改了后续判断所需的像素值。

以下是参考的修正代码,添加了一些处理细节:

#include <opencv2/opencv.hpp>

using namespace cv;

void processImage(Mat& img) {
    // 确保处理的是单通道图像
    if (img.channels() != 1) {
      cvtColor(img, img, COLOR_BGR2GRAY);
    }

    // 创建一个副本,以存储修改后的结果
    Mat result = img.clone();

    // 遍历图像的每个像素(不包括边缘像素,因为它们没有足够的邻居)
    for (int y = 2; y < img.rows - 2; ++y) {
      for (int x = 2; x < img.cols - 2; ++x) {
            // 获取当前像素值
            uchar currentValue = result.at<uchar>(y, x);

            // 如果当前像素为白色(假设白色为255)
            if (currentValue == 255) {
                // 检测x轴前面第2和第3像素
                uchar xFront2Value = result.at<uchar>(y, x - 2);
                uchar xFront3Value = result.at<uchar>(y, x - 3);

                // 设置前面1像素
                if (xFront2Value == 0 && xFront3Value == 0) {
                  img.at<uchar>(y, x - 1) = 255;
                } else if (xFront2Value == xFront3Value && xFront2Value != 0) {
                  img.at<uchar>(y, x - 1) = xFront2Value;
                }

                // 检测x轴后面第2和第3像素
                uchar xAfter2Value = result.at<uchar>(y, x + 2);
                uchar xAfter3Value = result.at<uchar>(y, x + 3);

                // 设置后面1像素
                if (xAfter2Value == 0 && xAfter3Value == 0) {
                  img.at<uchar>(y, x + 1) = 255;
                } else if (xAfter2Value == xAfter3Value && xAfter2Value != 0) {
                  img.at<uchar>(y, x + 1) = xAfter2Value;
                }

                // 检测y轴上面第2和第3像素
                uchar yUp2Value = result.at<uchar>(y - 2, x);
                uchar yUp3Value = result.at<uchar>(y - 3, x);

                // 设置上面1像素
                if (yUp2Value == 0 && yUp3Value == 0) {
                  img.at<uchar>(y - 1, x) = 255;
                } else if (yUp2Value == yUp3Value && yUp2Value != 0) {
                  img.at<uchar>(y - 1, x) = yUp2Value;
                }

                // 检测y轴下面第2和第3像素
                uchar yDown2Value = result.at<uchar>(y + 2, x);
                uchar yDown3Value = result.at<uchar>(y + 3, x);

                // 设置下面1像素
                if (yDown2Value == 0 && yDown3Value == 0) {
                  img.at<uchar>(y + 1, x) = 255;
                } else if (yDown2Value == yDown3Value && yDown2Value != 0) {
                  img.at<uchar>(y + 1, x) = yDown2Value;
                }
            }
      }
    }
}

关键修改点:

- 确保输入图像为单通道;
- 使用克隆图像存储处理结果,以避免在同一个循环中读取已被修改的数据;
- 保证像素访问正确,使用 `<uchar>` 指定访问灰度值。

尝试这段代码看看是否能达到预期效果。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
页: [1]
查看完整版本: 像素处理问题