【问题标题】:C++ OpenCV function "mat.at<Vec3b>(Point(j, i))" not yielding correct pixel values and crashingC++ OpenCV 函数“mat.at<Vec3b>(Point(j, i))”没有产生正确的像素值并崩溃
【发布时间】:2016-04-14 10:13:18
【问题描述】:

我正在尝试制作一个简单的程序来读取输入图像的像素值 (BGR) 并制作相同大小的输出图像,但如果原始图片中的像素是白色的,则输出图像的像素(相同位置)为蓝色,如果像素不是白色,则使输出图像中的相同像素为黑色。但是我很难让它正常工作。这似乎很容易,但它的表现并不像我期望的那样。下面是我的代码:

Mat input;
Mat output;
Vec3b color;
input = imread("C:/temp/COLORTEST2.png", CV_LOAD_IMAGE_UNCHANGED);
output = input;
int rows = input.rows;
int cols = input.cols;
int Blue, Green, Red;
cout << "Rows: " << rows << "\nColumns: " << cols << "\nTotal Pixels: " << (rows*cols) << endl;
cout << "Calculating...\n\n";
for (j = 0; j < rows; j++)
{
    for (i = 0; i < cols; i++)
    {
        color = input.at<Vec3b>(Point(j, i));
        Blue = color.val[0];
        Green = color.val[1];
        Red = color.val[2];

        if (Blue == 255 && Green == 255 && Red == 255){
            W++; //White count +1
            output.at<Vec3b>(Point(j, i))[0] = 255;
            output.at<Vec3b>(Point(j, i))[1] = 0;
            output.at<Vec3b>(Point(j, i))[2] = 0;
        }
        else{
            NW++; //NonWhite count +1
            output.at<Vec3b>(Point(j, i))[0] = 0;
            output.at<Vec3b>(Point(j, i))[1] = 0;
            output.at<Vec3b>(Point(j, i))[2] = 0;
            //cin >> response;
        }

    }
}
cout << "White Pixels: " << W << "\nNon-White Pixels: " << NW << endl;
imwrite("C:/temp/Output.png", output);
waitKey();

就像我说的,看起来很简单,但是当我运行它时它崩溃了。如果我在 for 循环中切换行和列,它运行良好,但输出图像看起来不像它应该的(带有几个黑色像素的垂直条带)。函数“mat.at(Point(j, i))”似乎是问题所在,看起来它在某个点崩溃,好像它在寻找一个几乎不存在的点,就好像行和列是切换了,但这没有意义...我还通过制作 MS 绘画图片 (20 x 30) 并将单个黑色像素放在 1x1 上对其进行了测试,它说在 1x1 时它的 BGR 为 255, 0, 0 ...这意味着它认为它是蓝色的并且更没有意义...我真的很难过,如果有人对这个功能及其工作原理有任何建议,我将非常感激。

编辑:这是输出和输入图像。这是我所说的错误,输出被剥离甚至没有完成:http://imgur.com/a/DPRlO 规格:
视窗 8.1
视觉工作室 2013
OpenCV 2.4.10
C++

【问题讨论】:

  • 请分享错误消息,它崩溃的行..任何有助于快速识别问题的信息

标签: c++ arrays opencv for-loop pixels


【解决方案1】:
output = input;

这是一个浅拷贝。这意味着每次更改输出数据时,都会更改输入数据。你应该这样做:

output = input.clone();

Point(x,y) => x 指的是列,y 指的是行。你正在做相反的事情。

改变那些:

for (j = 0; j < rows; j++)
{
    for (i = 0; i < cols; i++)
    {

对那些:

for (j = 0; j < cols; j++)
{
    for (i = 0; i < rows; i++)
    {

顺便说一句,BLUE,RED,GREEN 应该是 uchar 而不是 int。

【讨论】:

  • 所以我做了你建议的改变,它工作得更好一点,但输出并没有真正意义。这是输入和输出:imgur.com/a/DPRlO 如您所见,有大量白线穿过它,好像它跳过了列,甚至没有完成最右边的部分。
  • 您确定像素是 100% 白色吗?例如,它们可能是 255 254 255。您应该检查 BLUE、RED、GREEN 是否在例如 240-255 的范围内,而不是正好 255
【解决方案2】:

我使用您提供的示例输入图像测试了您的代码。您的输入图像包含 alpha 通道。所以它是一个四通道图像。您应该使用Vec4b 而不是Vec3b 以获得正确的结果。 否则更改语句 input = imread(imgpath, CV_LOAD_IMAGE_UNCHANGED) 到 input = imread(imgpath, CV_LOAD_IMAGE_COLOR) 以 3 通道 BGR 格式加载图像并继续 Vec3b。

【讨论】:

  • 为什么不需要积分?它与毫无意义地使用它有什么不同?此外,输出图像是条纹的,甚至没有完成:imgur.com/a/DPRlO
  • 抱歉答案不准确。我编辑了我的答案并为您面临的问题提供了正确的解决方案。
  • 使用指针我们需要像这样访问像素..img.at(Point(col,row)) 。没有指针你可以像这样访问.input.at((行,列))
  • 啊,我不知道它是 4 通道。这解决了这个问题,我不知道这甚至是一个问题......或者它甚至是 4 通道开始,对于 OpenCV 来说仍然是新的。非常感谢!
猜你喜欢
  • 1970-01-01
  • 2016-01-09
  • 2019-09-17
  • 1970-01-01
  • 1970-01-01
  • 2022-01-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多