How to come from C# stream to OpenCV Mat by using c++/cli?

北慕城南 提交于 2021-02-18 08:36:42

问题


I am reading some image from Azure Blob storage. This is a stream in c#.

In c++/cli I need to do this:

cv::Mat img_object = imdecode(data, IMREAD_UNCHANGED);

where data is of type cv::InputArray

so the question is how do I best get from c# to the cv::mat?

public ref class Client
{
public:
    // TODO: Add your methods for this class here.
    void Method(Stream ^ img1, Stream ^ img2);
};

void Client::Method(...){

}

I just put in Stream ^ img1, Stream ^img2, thats not a requirement, just not sure what is the best way to get from the c# stream to the cv::Mat class.

I know I could save the stream on a temp file location and use imread instead, but would be nice just to do it in memory.

in csharp i just have somehting like this: (I know its not the correct methods, but for the purpose of this example it illustrate the point).

Client client = new Client();
client.Method(blob.GetStream(), blob.GetStream())

Update : First try

void CVService::Stiching::StichingClient::FindHomography(cli::array<unsigned char>^ pCBuf1, cli::array<unsigned char> ^ pCBuf2)
{

    pin_ptr<unsigned char> data1 = &pCBuf1[0];
    pin_ptr<unsigned char> data2 = &pCBuf2[0];  

    Mat img_object = imdecode(*data1,IMREAD_COLOR);
    Mat img_scene = imdecode(*data2, IMREAD_COLOR);

    if (!img_object.data || !img_scene.data)
    {
        return;
    }
    imwrite("c:\\test.jpg", img_object);
}

and

public class WebRole : RoleEntryPoint
{
    public override bool OnStart()
    {
        // For information on handling configuration changes
        // see the MSDN topic at http://go.microsoft.com/fwlink/?LinkId=166357.

        StichingClient client = new StichingClient();

        client.FindHomography(ReadByteArray(path1).Result
            , ReadByteArray(path2).Result);

        return base.OnStart();
    }

    private async Task<byte[]> ReadByteArray(string p)
    {
        using (var fs = File.OpenRead(p))
        {
            using (var ms = new MemoryStream())
            {
                await fs.CopyToAsync(ms);

                return ms.ToArray();
            }
        }
    }

}

Problem is that the loaded cv::mat is having data== 0 and not writing the image to disk. I have verified that the passed char arrays contains data. Is there any way to find out why imdecode do not decode the images?

update 2

the following test in c++/cli code part works:

Mat test1 = imread("DSC_023.tif");
std::vector<unsigned char> buf;     
imencode(".jpg", test1, buf);
Mat test2 = imdecode(buf, IMREAD_COLOR);

With the above 4 lines the test2 is the loaded image and imdecode works. So wondering why it do not work when the data comes in as byte arrays


回答1:


So heres is my solution. It can be cleaned up ofcause but it works now.

void CVService::Stiching::StichingClient::FindHomography(cli::array<unsigned char>^ pCBuf1, cli::array<unsigned char> ^ pCBuf2)
{

    pin_ptr<unsigned char> data1 = &pCBuf1[0];
    pin_ptr<unsigned char> data2 = &pCBuf2[0];  

    pin_ptr<System::Byte> p1 = &pCBuf1[0];
    unsigned char* pby1 = p1;
    Mat img_data1(pCBuf1->Length, 1, CV_8U, pby1);

    pin_ptr<System::Byte> p2 = &pCBuf2[0];
    unsigned char* pby2 = p2;
    Mat img_data2(pCBuf2->Length, 1, CV_8U, pby2);

    cv::Mat img_object = imdecode(img_data1, IMREAD_UNCHANGED);
    cv::Mat img_scene = imdecode(img_data2, IMREAD_UNCHANGED);

    if (!img_object.data || !img_scene.data)
    {
        return;
    }
    imwrite("img_object.jpg", img_object);
    imwrite("img_scene.jpg", img_scene);
}

I got this working with converting two images loaded from Azure Blob storage in memory and can now do my opencv stuff on the images. The test here just write the two passed images to the file system.



来源:https://stackoverflow.com/questions/21649136/how-to-come-from-c-sharp-stream-to-opencv-mat-by-using-c-cli

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!