C++ 中 cv::Rectangle 的问题

Posted

技术标签:

【中文标题】C++ 中 cv::Rectangle 的问题【英文标题】:Problems with cv::Rectangle in C++ 【发布时间】:2017-10-18 10:17:30 【问题描述】:

在 cv :: mat 中绘制矩形时遇到问题。我正在 Unity 和 C++ 之间进行通信以生成 android 应用程序。

我使用统一的 webcamtexture 相机,并使用 PInvoke 方法将信息发送到 C++。一旦在 C++ 代码中,我想绘制一个矩形,但我在图像中得到了多个(见图),我真的不明白为什么。希望大家帮我附上C++和C#代码。

C#

void Update()

    //texto.text = texto.text + " / "+ testo().ToString();
    imgData = null;
    imgData = new byte[width * height * 3];
    resultado = null;
    resultado = new byte[width * height * 3];
    color = webcam.GetPixels32();
    int bytesPerPixel = 3;
    const int indexR = 0;
    const int indexG = 1;
    const int indexB = 2;
    for (var i = 0; i < color.Length; i++)
    
        imgData[(i * bytesPerPixel) + indexR] = color[i].r;
        imgData[(i * bytesPerPixel) + indexG] = color[i].g;
        imgData[(i * bytesPerPixel) + indexB] = color[i].b;
    
    color = null;
    ProcessFrame(imgData, resultado, 0, 0, 0,0, nuevo);
    nuevo = false;
    textura2 = new Texture2D(width, height, TextureFormat.RGB24, false);
    textura2.LoadRawTextureData(resultado);
    textura2.Apply();
    renderer.material.mainTexture = textura2;
    textura2 = null;
    Resources.UnloadUnusedAssets();

C++

void ProcessFrame(unsigned char* arr, unsigned char* resu,int posx, int posy, int poswidth, int posheight,bool nuevo) 
    Mat dst;//dst image
    trueRect.x = 150;
    trueRect.y = 150;
    trueRect.width = 100;
    trueRect.height = 100;
    wi = poswidth;
    he = posheight;
    mal = 20;
    dst = Mat(tamWid,tamHeid,CV_8UC3, arr);
    rectangle(dst, Point(50,50), Point(100,100), cv::Scalar(0, 255, 255));
    copy(dst.datastart, dst.dataend, resu);

【问题讨论】:

我不能肯定地说,但我的猜测是你已经用行移动了列,即 OpenCV 存储图像数据列和 Unity (OpenGL) 行(或其他方式)。您可以调试此 C++ 代码并使用 ImageWatch 插件检查矩阵吗?或者简单地使用cv::imwrite 保存 dst。此外,您应该先复制 dst 然后再绘制它。至于现在你改变原始图像并复制它,所以两者都有矩形。 抱歉,我不确定你在告诉我什么。我在之前的函数中传递了图像大小的信息,它的分辨率为 640x480。我不明白你想用边缘说什么,更不用说你如何解决它了。关于 Debug,我不能使用,因为我正在统一使用共享库来创建 Android 应用程序。 @R2RT opencv 是行专业的。问题是dst = Mat(tamWid,tamHeid,CV_8UC3, arr); 它是构造函数中的行、列,所以它应该是dst = Mat(tamHeid,tamWid,CV_8UC3, arr); 然后您还必须检查数据是按列还是按行,如果是按列,则需要将其保留为在垫子之前和转置 @api55 是的,我认为你是对的。你应该让它成为一个答案。 Urko,试试Mat(tamHeid,tamWid,CV_8UC3, arr); 成功了,谢谢大家解决方案:Mat(tamHeid,tamWid,CV_8UC3, arr); 【参考方案1】:

为了完整起见,我将发布答案。

问题出在一行

dst = Mat(tamWid,tamHeid,CV_8UC3, arr); 

constructor of Mat 将前两个参数行和列作为前两个参数,在您的情况下是列和行。

应该是这样的:

dst = Mat(tamHeid,tamWid,CV_8UC3, arr);

其他注意事项

正如我在 cmets 中所说,您应该注意某些可能的错误来源,因为 OpenCV 和 Unity 中的约定不同。其中之一是您的 2D 坐标系的原点。在 OpenCV 中位于左上角,在 Unity 中,或者至少 GetPixels32 函数位于图像的左下角。

另一个可能的问题是色彩空间。 OpenCV 在加载、保存和其他功能时需要 BGR 图像,而在其他框架中它们使用 32 位的 RGB 或 RGBA。

【讨论】:

以上是关于C++ 中 cv::Rectangle 的问题的主要内容,如果未能解决你的问题,请参考以下文章

cv2.rectangle() 调用重载方法,虽然我给出了其他参数

为啥 cv2.rectangle 有时会返回 np.ndarray,而有时会返回 cv2.UMat

OpenCV cv2.rectangle 输出二值图像

利用cv2.rectangle()绘制矩形框(python)

cv2.rectangle:TypeError:由名称('厚度')和位置(4)给出的参数

cv2.rectangle()、cv2.putText()和cv2.imwrite()用法