2

i have a unity C# script that instantiates a Color32[] array to pass the pointer to a C++ method that sits in a DLL file. Within the C++ script, the pointer links the Color32[] array to a cv::Mat object that gets instantiated. Also within the C++ script, i retrieve a videostream and put it inside the cv::Mat object and image process it. After that within Unity, I assign the updated Color32[] array to a Texture2D and try to display it using a Sprite Renderer.

ISSUE: From Unity side the Color32[] seems to be empty (also when i put the code into the update() hook definition of the C# script). From C++ side the cv::Mat object holds the correctly processed image with multiple colors. (In case you wonder i reduced the used if-cases for clarity here). A helper method showed that there is only 1 color within the Color32[] after processing looking from c#.

For the Unity and C++ interaction I used these two example projects: by thomas and by amin.

I fear there could be an issue regarding data handling between managed and unmanaged execution which is why i ask for help.

Unity script:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Runtime.InteropServices;

[RequireComponent(typeof(SpriteRenderer))]
public class SpriteMaker : MonoBehaviour
{
    SpriteRenderer rend;

    private Color32[] rawImage;

    internal static class OpenCVInterop
    {
        [DllImport("ImageProcessor_dll")]
        internal static extern void Init();

        [DllImport("ImageProcessor_dll")]
        internal static extern void ImageProcessing(ref Color32[] rawImage);
    }

    void Start()
    {
        
        OpenCVInterop.Init();

        rawImage = new Color32[640 * 240];

        OpenCVInterop.ImageProcessing(ref rawImage);

        Texture2D tex = new Texture2D(640, 240);
        tex.SetPixels32(rawImage);
        tex.Apply();

        rend = GetComponent<SpriteRenderer>();
        Sprite newSprite = Sprite.Create(tex, new Rect(0, 0, tex.width, tex.height), Vector2.one * 0.5f);

        rend.sprite = newSprite;

    }
}

C++ script:

#include "pch.h"
#include <iostream>
#include "opencv2/opencv.hpp"
#include "opencv2/highgui.hpp"

using namespace cv;
using namespace std;

VideoCapture _capture;

struct Color32
{
    uchar red;
    uchar green;
    uchar blue;
    uchar alpha;
};

extern "C" void __declspec(dllexport) __stdcall  Init()
{
    //implement size handoff for more dynamic
    _capture.open(0);

    if (_capture.isOpened())
    {
        std::cout << "VideoCapture is opened" << std::endl;
    }
}

extern "C" void __declspec(dllexport) __stdcall ImageProcessing(Color32 **rawImage_Inbound)
{
    Mat rawImage(640,240,CV_8UC4,*rawImage_Inbound);

    // for debugging -> shows black image
    imshow("frame", rawImage);

    _capture >> rawImage;

    for (int y = 0; y < rawImage.rows; y++)
    {
        for (int x = 0; x < rawImage.cols; x++)
        {
            Vec3b& color = rawImage.at<Vec3b>(Point(x, y));
            float color0_int = color[0];
            float color2_int = color[2];
            float ID = (color2_int - color0_int) / (color2_int + color0_int);

            if (ID >= -1 && ID < 0)
            {
                color[0] = 128;
                color[1] = 128;
                color[2] = 128;
            }
            else
            {
                color[0] = 255;
                color[1] = 0;
                color[2] = 0;
            }
            rawImage.at<Vec3b>(Point(x, y)) = color;
        }
    }
    // for debugging -> shows processed image
    imshow("frame", rawImage);
}
Lennart
  • 33
  • 7
  • I now follow a different approach that recognizes the necessity to have the shared container fixed and also just handoff the pointer. However it also makes problems as documented [here](https://stackoverflow.com/q/70214523/15147859?sem=2) – Lennart Dec 03 '21 at 12:57

0 Answers0