基于本地OpenCV的Unity Android应用程序

4
我有一个小疑问,希望您能解决它。
我想在Unity中创建一个Android应用程序。该应用程序包括激活设备的相机并在屏幕上查看。为此,我想基于基于OpenCV的本地C ++代码进行操作。
我已经生成了代码,但是当我运行应用程序时,我可以看到场景但无法看到图像,并且我感觉这是由于我没有正确使用OpenCV的VideoCapture函数导致的。 您能帮忙吗? 我将附上代码:
C ++:
__declspec(dllexport) void iniciar(int& widt, int& heigh) {
camera.open(0);
if (!camera.isOpened())
{
    return;
}
widt = (int)camera.get(CV_CAP_PROP_FRAME_WIDTH);
heigh = (int)camera.get(CV_CAP_PROP_FRAME_HEIGHT);
trueRect.x = 5;
trueRect.y = 5;
trueRect.width = 100;
trueRect.height = 100;
midX = 1;
midY = 1;
wi = 0;
he = 0;
}


__declspec(dllexport)
void video(unsigned char* arr) {
Mat frame;
Mat resi;
Mat dst;//dst image
camera >> frame;
if (frame.empty()) {
    return;
}
flip(frame, dst,1);
//resize(dst, resi, Size(width, height));
cv::cvtColor(dst, dst, COLOR_BGR2RGB);
copy(dst.datastart, dst.dataend, arr);
}

C#:

public class camara : MonoBehaviour {

[DllImport("NativoPrincipio")]
public static extern void video(byte[] img);

[DllImport("NativoPrincipio")]
public static extern void iniciar(ref int widt, ref int heigh);

WebCamTexture back;
Texture2D textura;
byte[] imgData;
int width = 0;
int height = 0;


// Use this for initialization
void Start () {
    back = new WebCamTexture();
    //GetComponent<Renderer>().material.mainTexture = back;
    //back.Play();
    iniciar(ref width, ref height);
}

// Update is called once per frame
void Update ()
{
    imgData = new byte[width * height * 4];
    video(imgData);
    textura = new Texture2D(width, height, TextureFormat.RGB24, false);
    textura.LoadRawTextureData(imgData);
    textura.Apply();
    GetComponent<Renderer>().material.mainTexture = textura;
    imgData = null;
    textura = null;

}}

imgData = new byte[width * height * 4]; 你为什么要乘以4?你的相机提供4通道图像吗? - zindarod
1
因为这是RGB图像,我尝试放置3个通道,但失败了。所以我放置了4个通道。 - Urko Sanchez Ortiz
1
RGB 意味着 3 个通道。如果您的代码失败了,那是因为其他原因。正如 @uelordi 建议的那样,尝试使用 Java 本地代码捕获图像,仅使用 OpenCV 处理图像。 - zindarod
2个回答

2
如果您已经在GitHub上托管了整个代码,或者如果您可以创建一个Gist,那就更好了。
但是,我认为您的相机帧为空。
我将尝试列举可能发生这种情况的原因。
首先,opencv视频捕获类camera.open(0)没有ffmpeg(不易于交叉编译为Android Native)。
如果您想从Android中使用C++本地相机,并且需要使用最新的NDK和API 24。
我看到您正在使用Unity的WebCamTexture类,但几乎可以肯定这个抓取的纹理是空的,因此您会在图像中看到黑屏幕。
您是否尝试搜索OpenCV的Unity插件?
我唯一看到的是这个(非免费): https://www.assetstore.unity3d.com/en/#!/content/21088 如果这行不通,您有任何办法将Java代码粘贴到Unity项目中吗? 因为在Java中进行相机捕获要容易得多。
希望这些线索能帮助您。
Ondo izan eta animo.
Unai.

1
在看了你的代码几分钟后,我发现了几个错误。
1. 你在C++端使用了“COLOR_BGR2RGB”。应该改为“COLOR_BGR2BGRA”,因为你在C#端使用了“TextureFormat.RGB24”。
2. 如果你想在C++插件中修改C#数组,你必须将其固定在内存中。在修改后,可以取消固定。如果不这样做,你将遇到一个很难找到的错误。
使用“fixed”关键字来固定数组,然后将其转换为“IntPtr”,并将其作为“IntPtr”传递给视频函数。最好还要传入数组大小,以免使用不存在的索引。
像这样:
[DllImport("NativoPrincipio")]
public static extern void video(IntPtr img, int count);

...

//Pin Memory
fixed (byte* p = imgData)
{
    video((IntPtr)p, imgData.Length);
}

第三步:最后,这是可选的,但您可能希望使用Java从相机读取图像,然后将该图像传递给C++中的OpenCV。我看到很多人在使用OpenCV从相机读取时遇到问题,更不用说它也很慢了。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接