鱼C论坛

 找回密码
 立即注册
查看: 286|回复: 3

像素处理问题

[复制链接]
发表于 2024-12-9 09:56:10 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
请帮我看一下下面的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像素一样的颜色。

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

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

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

  15.                                 // 设置前面1像素
  16.                                 if (xFront2Value == 0 && xFront3Value == 0) {
  17.                                         img.at<uchar>(x - 1, y) = 255;
  18.                                 }
  19.                                 else if (xFront2Value == xFront3Value && xFront2Value != 0) {
  20.                                         img.at<uchar>(x - 1, y) = xFront2Value;
  21.                                 }
  22.                                 else if (xAfter2Value == 0 && xAfter3Value == 0) {
  23.                                         img.at<uchar>(x + 1, y) = 255;
  24.                                 }
  25.                                 else if (xAfter2Value == xAfter3Value && xAfter2Value != 0) {
  26.                                         img.at<uchar>(x + 1, y) = xAfter2Value;
  27.                                 }

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

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

  34.                                 // 设置上面1像素
  35.                                 if (yUp2Value == 0 && yUp3Value == 0) {
  36.                                         img.at<uchar>(x, y - 1) = 255;
  37.                                 }
  38.                                 else if (yUp2Value == yUp3Value && yUp2Value != 0) {
  39.                                         img.at<uchar>(x, y - 1) = yUp2Value;
  40.                                 }
  41.                                 else if (yDown2Value == 0 && yDown3Value == 0) {
  42.                                         img.at<uchar>(x, y + 1) = 255;
  43.                                 }
  44.                                 else if (yDown2Value == yDown3Value && yDown2Value != 0) {
  45.                                         img.at<uchar>(x, y + 1) = yDown2Value;
  46.                                 }

  47.                         }
  48.                 }
  49.         }
  50. }
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

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

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

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

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

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

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

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

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

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

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

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

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

  39.                                 // 设置下面1像素
  40.                                 if (yDown2Value == 0 && yDown3Value == 0) {
  41.                                         img.at<uchar>(y + 1, x) = 255;
  42.                                 } else if (yDown2Value == yDown3Value && yDown2Value != 0) {
  43.                                         img.at<uchar>(y + 1, x) = yDown2Value;
  44.                                 }
  45.                         }
  46.                 }
  47.         }
  48. }
复制代码


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

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 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) {
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-12-9 10:23:23 | 显示全部楼层
cxnet 发表于 2024-12-09 10:19
我用了这段代码后还是一样的错误,我把 下面2行后面的 ...


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

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

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

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

  1. #include <opencv2/opencv.hpp>

  2. using namespace cv;

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

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

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

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

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

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

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

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

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

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

  47.                 // 设置下面1像素
  48.                 if (yDown2Value == 0 && yDown3Value == 0) {
  49.                     img.at<uchar>(y + 1, x) = 255;
  50.                 } else if (yDown2Value == yDown3Value && yDown2Value != 0) {
  51.                     img.at<uchar>(y + 1, x) = yDown2Value;
  52.                 }
  53.             }
  54.         }
  55.     }
  56. }
复制代码


关键修改点:

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

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

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-5-10 00:16

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表