【问题标题】:OpenCV display the wrong colorOpenCV显示错误的颜色
【发布时间】:2020-05-12 02:43:37
【问题描述】:

我正在使用 C++ 处理 OpenCV。我想创建一个具有 3 种颜色的图像:红色、白色和黑色。详细地说,我希望背景为红色,然后根据某些条件,部分为白色,部分为黑色。

我遇到的问题是,当我将颜色设置为白色时,它变成了蓝色。

有人知道为什么会发生这种情况以及如何解决吗?

这是我的代码:

    //initial image total red

    cv::Mat image(Size(w, h), CV_8UC3, cv::Scalar(0, 0, 255));          

    for (int i = 0; i < h; i++) {
        for (int j = 0; j < w; j++) {
            int pixel_v = (int)imggray.at<uchar>(i,j);
            if (pixel_v < 200) {                
                int pixel_bl = (int)imgBool.at<uchar>(i, j);
                if (pixel_bl > 200) {
                    //HERE A WANT WHITE PIXELS, but they are blue
                    image.at<Vec3b>(i, j) = (255, 255, 255);                        
                }
                else {
                    //black: this works
                    image.at<Vec3b>(i, j) = (0, 0, 0);

                }
            }


        }
    }

【问题讨论】:

  • OpenCV 显示正确的颜色,但您输入错误的值。
  • 试试:image.at(i, j) = cv::Vec3b(255, 255, 255);
  • nuzhny:是的,之所以这么叫,是因为我改变了那些像素的颜色!它们变成蓝色而不是白色@Swordfish:可能是。 opencv 中白色的正确值是多少?不是(255,255,255)吗?
  • (255, 255, 255) 没有做你认为它做的事情(见comma operator。)它的计算结果只是255
  • 我看错了你设置的(255, 255, 255);是错误的。

标签: c++ opencv rgb


【解决方案1】:

OpenCV 使用图像格式 BGR(Blue, Green Red)

当你写下这一行时:

 image.at<Vec3b>(i, j) = (255, 255, 255);             

相当于:

image.at<Vec3b>(i, j) = (255);             

(请参阅this SO answer 解释原因。)

仅将第一个通道设置为最大,并且恰好是蓝色。

您需要做的是编辑整个像素,如下所示:

    // get pixel
    Vec3b color = image.at<Vec3b>(Point(x,y));

    color[0] = 255;
    color[1] = 255;
    color[2] = 255;

    // set pixel
    image.at<Vec3b>(Point(x,y)) = color;

Borrowed from this answer

所以您的代码需要如下所示:

cv::Mat image(Size(w, h), CV_8UC3, cv::Scalar(0, 0, 255));          

for (int i = 0; i < h; i++) {
    for (int j = 0; j < w; j++) {
        int pixel_v = (int)imggray.at<uchar>(i,j);
        if (pixel_v < 200) {                
            int pixel_bl = (int)imgBool.at<uchar>(i, j);
            if (pixel_bl > 200) {
                //HERE A WANT WHITE PIXELS, but they are blue
                Vec3b color = image.at<Vec3b>(Point(i,j));
                color[0] = 255;
                color[1] = 255;
                color[2] = 255;
                image.at<Vec3b>(Point(i,j)) = color;                   
            }
            else {
                image.at<Vec3b>(i, j) = (0, 0, 0);

            }
        }
    }
}

【讨论】:

  • 它可以工作,但是以这种方式 Vec3b 颜色;颜色[0] = 255;颜色[1] = 255;颜色[2] = 255; image.at(i, j) = 颜色;非常感谢您对第一个频道的解释。
  • 太好了,是的,您无需读出颜色即可开始使用。您甚至可以将 Vec3b 颜色定义移到循环之外,以节省每次创建新对象的时间,这样会更快。
【解决方案2】:

我正在使用带有 C++ 的 opencv。我从 java 接收图像,然后使用此方法将其放入缓冲区:

private fun YUV_420_888_dataToBuffer(image: Image): ByteArray? {
     try {
   val imageWidth = image.width
   val imageHeight = image.height
   val planes = image.planes
   val data = ByteArray(imageWidth * imageHeight *  ImageFormat.getBitsPerPixel(ImageFormat.YUV_420_888) / 8 )
   var offset = 0
   for (plane in planes.indices) {
       val buffer = planes[plane].buffer
       val rowStride = planes[plane].rowStride

       val pixelStride = planes[plane].pixelStride
       val planeWidth = if (plane == 0) imageWidth else imageWidth / 2
       val planeHeight = if (plane == 0) imageHeight else imageHeight / 2
       if (pixelStride == 1 && rowStride == planeWidth) {
           // Copy whole plane from buffer into |data| at once.
           buffer[data, offset, planeWidth * planeHeight]
           offset += planeWidth * planeHeight
       } else {
           // Copy pixels one by one respecting pixelStride and rowStride.
           val rowData = ByteArray(rowStride)
           for (row in 0 until planeHeight - 1) {
               buffer[rowData, 0, rowStride]
               for (col in 0 until planeWidth) {
                   data[offset++] = rowData[col * pixelStride]
               }
           } 
           buffer[rowData, 0, Math.min(rowStride, buffer.remaining())]
           for (col in 0 until planeWidth) {
               data[offset++] = rowData[col * pixelStride]
           }
       }
   }
   return data
  } catch (e: Exception) {
   return null
 }
    }

在 c++ 方面,我正在从字节数组创建一个 Mat,如下所示:

 Mat * myuv = new Mat(width, height, CV_8UC1, (unsigned char *)  data);

 cvtColor(*myuv, *myuv, COLOR_YUV420sp2RGBA, 4);

这里出了什么问题?

【讨论】:

  • 请打开您自己的问题,而不是在另一个问题下发表评论。
  • 我不是喝醉了,但我发誓这是我自己提出的问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-04-22
  • 2020-11-09
  • 2018-05-18
  • 1970-01-01
  • 2019-02-28
  • 1970-01-01
相关资源
最近更新 更多