使用 OpenCV VideoCapture (C++) 更新 Texture2D (Unity) 并使用 Sprite Renderer 显示时混淆输出
Confusing output when updating a Texture2D (Unity) with OpenCV VideoCapture (C++) and displaying with Sprite Renderer
背景: 类似问题 我使用了答案中的代码段。但是,它不能解决我的问题。我必须补充一点,我是Unity编程的初学者!
目标: 通过 opencv c++ 脚本接收视频直播,并从 unity 脚本访问它以显示在场景中。
在场景中显示直播的方法: Sprite渲染器。
问题: 查看下面的屏幕截图,网络摄像头输出显示四次并排并带有条纹(它应该显示我在摄像头前面)。 imshow 显示正确的网络摄像头图像。
当前代码:
C++:
...
extern "C" void __declspec(dllexport) Init()
{
_capture.open(0);
}
extern "C" void __declspec(dllexport) NDVIStreamer(unsigned char* data, int width, int height)
{
Mat _currentFrame(height, width, CV_8UC4, data);
_capture >> _currentFrame;
imshow("lennart", _currentFrame);
memcpy(data, _currentFrame.data, _currentFrame.total() * _currentFrame.elemSize());
}
注意: 将数据指针分配给 _currentFrame 并没有改变任何东西——从我的角度来看——这应该已经完成了工作。它没有。
C#:
...
[RequireComponent(typeof(SpriteRenderer))]
public class SpriteMaker : MonoBehaviour
{
SpriteRenderer rend;
[DllImport("NDVIstreamer_dll2")]
private static extern void NDVIStreamer(IntPtr data, int width, int height);
[DllImport("NDVIstreamer_dll2")]
private static extern void Init();
private Texture2D tex;
private Color32[] pixel32;
private GCHandle pixelHandle;
private IntPtr pixelPtr;
void Start()
{
rend = GetComponent<SpriteRenderer>();
tex = new Texture2D(640, 240, TextureFormat.RGBA32, false);
pixel32 = tex.GetPixels32();
//Pin pixel32 array
pixelHandle = GCHandle.Alloc(pixel32, GCHandleType.Pinned);
//Get the pinned address
pixelPtr = pixelHandle.AddrOfPinnedObject();
Init();
MatToTexture2D();
//create a sprite from that texture
Sprite newSprite = Sprite.Create(tex, new Rect(0, 0, tex.width, tex.height), Vector2.one * 0.5f);
rend.sprite = newSprite;
pixelHandle.Free();
}
void MatToTexture2D()
{
NDVIStreamer(pixelPtr, tex.width, tex.height);
tex.SetPixels32(pixel32);
tex.Apply();
}
}
添加此代码即可完成工作(代码取自程序员):
Mat resizedMat(height, width, _currentFrame.type());
resize(_currentFrame, resizedMat, resizedMat.size());
Mat argb_img;
cvtColor(resizedMat, argb_img, COLOR_RGB2BGRA);
vector<Mat> bgra;
split(argb_img, bgra);
swap(bgra[0], bgra[3]);
swap(bgra[1], bgra[2]);
flip(argb_img, argb_img, -1);
背景: 类似问题
目标: 通过 opencv c++ 脚本接收视频直播,并从 unity 脚本访问它以显示在场景中。
在场景中显示直播的方法: Sprite渲染器。
问题: 查看下面的屏幕截图,网络摄像头输出显示四次并排并带有条纹(它应该显示我在摄像头前面)。 imshow 显示正确的网络摄像头图像。
当前代码:
C++:
...
extern "C" void __declspec(dllexport) Init()
{
_capture.open(0);
}
extern "C" void __declspec(dllexport) NDVIStreamer(unsigned char* data, int width, int height)
{
Mat _currentFrame(height, width, CV_8UC4, data);
_capture >> _currentFrame;
imshow("lennart", _currentFrame);
memcpy(data, _currentFrame.data, _currentFrame.total() * _currentFrame.elemSize());
}
注意: 将数据指针分配给 _currentFrame 并没有改变任何东西——从我的角度来看——这应该已经完成了工作。它没有。
C#:
...
[RequireComponent(typeof(SpriteRenderer))]
public class SpriteMaker : MonoBehaviour
{
SpriteRenderer rend;
[DllImport("NDVIstreamer_dll2")]
private static extern void NDVIStreamer(IntPtr data, int width, int height);
[DllImport("NDVIstreamer_dll2")]
private static extern void Init();
private Texture2D tex;
private Color32[] pixel32;
private GCHandle pixelHandle;
private IntPtr pixelPtr;
void Start()
{
rend = GetComponent<SpriteRenderer>();
tex = new Texture2D(640, 240, TextureFormat.RGBA32, false);
pixel32 = tex.GetPixels32();
//Pin pixel32 array
pixelHandle = GCHandle.Alloc(pixel32, GCHandleType.Pinned);
//Get the pinned address
pixelPtr = pixelHandle.AddrOfPinnedObject();
Init();
MatToTexture2D();
//create a sprite from that texture
Sprite newSprite = Sprite.Create(tex, new Rect(0, 0, tex.width, tex.height), Vector2.one * 0.5f);
rend.sprite = newSprite;
pixelHandle.Free();
}
void MatToTexture2D()
{
NDVIStreamer(pixelPtr, tex.width, tex.height);
tex.SetPixels32(pixel32);
tex.Apply();
}
}
添加此代码即可完成工作(代码取自程序员
Mat resizedMat(height, width, _currentFrame.type());
resize(_currentFrame, resizedMat, resizedMat.size());
Mat argb_img;
cvtColor(resizedMat, argb_img, COLOR_RGB2BGRA);
vector<Mat> bgra;
split(argb_img, bgra);
swap(bgra[0], bgra[3]);
swap(bgra[1], bgra[2]);
flip(argb_img, argb_img, -1);