convert char** to cv::Mat

asked 2016-02-07 06:16:38 -0600

Bilityuk gravatar image

updated 2016-02-07 06:26:48 -0600

Hi to everyone! I am trying to convert raw image data from my IP camera to cv::Mat. But can't do it properly. My IP camera use it's own library to retrieve images. This function looks like

GetVideoData(hwnd, (char**)&Frame, &dataLen, videofmt,&mediaSpeed);

Frame has a data buffer of type char data[0] in it's struct; Can anybody help me to find out how to convert Frame->data to cv::Mat?

I tried to do it like:

cv::Mat cameraFrame = cv::Mat(h, w, CV_8UC1, Frame->data);

But when i am trying to show it with imshow("name",cameraFrame); it looks like gray and very pure image.. C:\fakepath\Screen.JPG

edit retag flag offensive close merge delete

Comments

what is Frame , exactly ? please show us the declaration. same with GetVideoData()

berak gravatar imageberak ( 2016-02-07 06:24:04 -0600 )edit

Here is the declaration of GetVideoData function:

/*
@Name: GetVideoData.
@Description: Get the data which decoded.
@Param handle: the handle of current connection information.
@Param data: Buffer,use to save data which get.
@Param len: Size of buf.
@Param outLen: The size of the data which get.
@Param videoFmt: Video format.
@Param mediaSpeed: The speed of the media data which get(bytes/s).  
*/
GetVideoData(CONNECTION handle, char **data, int *outLen, FOSDECFMT videoFmt, int* mediaSpeed);
Bilityuk gravatar imageBilityuk ( 2016-02-07 06:37:00 -0600 )edit

Here is struct of the Frame datatype:

typedef struct   
{ 
    MEDIATYPE  type; //Is video or audio
    DECFMT  fmt; //The format of video or audio.
    int  isKey;     
    int  frameTag;  
    union{ 
        VIDEO_INFO      video; //Media type is video.
        AUDIO_INFO      audio; //Media type is audio.
    } media;
    unsigned long long  pts; //Pts.
    unsigned int len;    //Size of data.
    char    data[0];    //Just data.
}VIDEO_DATA;
Bilityuk gravatar imageBilityuk ( 2016-02-07 06:40:23 -0600 )edit

I need only Frame->data. This is the data of the image from IP camera stream. Finally i need to convert it to cv::Mat, make facerecognition processing, and convert the image back to char* data, that i can draw it with IP camera function

DrawVideoIamge(char *Videodata, int Total_ch, int ch);
Bilityuk gravatar imageBilityuk ( 2016-02-07 06:46:01 -0600 )edit

Also i tried to use another way of convertion, and it behaves different. Here i convert the Frame->data to cv:Mat:

Mat cameraFrame;
Mat InImg(h, w,CV_8UC1);  
memcpy(InImg.data,Frame->data, sizeof(char)*w*h);       
InImg.copyTo(cameraFrame);

make some face recognition processing with cameraFrame and finally trying to draw the image this way:

DrawVideoIamge((char*)cameraFrame.data, 1, 0);

And now i got the color image, but it seems like it mirrored or i dont know how to explaine. Here is a link i upload the screen shot.

Image and video hosting by TinyPic</a">link text

Bilityuk gravatar imageBilityuk ( 2016-02-07 06:54:54 -0600 )edit

If i use imshow() instead of DrawVideoIamge(). I've got the gray image like on the previos screen i posted.

Bilityuk gravatar imageBilityuk ( 2016-02-07 07:09:18 -0600 )edit

try cv::Mat cameraFrame = cv::Mat(h, w, CV_8UC3, Frame->data);

sturkmen gravatar imagesturkmen ( 2016-02-07 07:30:56 -0600 )edit

CV_8UC3 doesn't work for this code(throws c000005):

cv::Mat cameraFrame = cv::Mat(h, w, CV_8UC3, Frame->data);

If use CV_8UC3 with this code:

Mat InImg(h, w,CV_8UC3);  
memcpy(InImg.data,pFrame->data, sizeof(char)*w*h);  
InImg.copyTo(cameraFrame);

Results the almost the same as for CV_8UC1. But now it lookes like triple image.

Here is CV_8UC3 with imshow():

Image and video hosting by TinyPic

Here is CV_8UC3 with DrawVideoIamge():

Image and video hosting by TinyPic

Bilityuk gravatar imageBilityuk ( 2016-02-07 08:03:36 -0600 )edit

try

Mat cameraFrame;
Mat InImg(h, w,CV_8UC3);  
memcpy(InImg.data,Frame->data, 3*w*h);       
InImg.copyTo(cameraFrame);
sturkmen gravatar imagesturkmen ( 2016-02-07 08:11:41 -0600 )edit

Just tried:

Mat cameraFrame;
Mat InImg(h, w,CV_8UC3);  
memcpy(InImg.data,Frame->data, 3*w*h);       
InImg.copyTo(cameraFrame);

It throws an exception on the memcpy line of code:

Image and video hosting by TinyPic

Bilityuk gravatar imageBilityuk ( 2016-02-07 08:42:02 -0600 )edit

what is dataLen value and w and h value?

GetVideoData(hwnd, (char**)&Frame, &dataLen, videofmt,&mediaSpeed);
sturkmen gravatar imagesturkmen ( 2016-02-07 09:27:38 -0600 )edit
1

I don't think copying to a Mat is your problem, but getting the right data. When I look at the Frame struct, I see that there's more than just the data container. So I think

GetVideoData(hwnd, (char**)&Frame, &dataLen, videofmt,&mediaSpeed);

could be the problem. At first I would check (char**)&Frame and try something like &Frame->data

matman gravatar imagematman ( 2016-02-07 10:47:05 -0600 )edit

I want to post the full function code. But there is not enough space for comments. I will post it in slices

Bilityuk gravatar imageBilityuk ( 2016-02-07 10:56:44 -0600 )edit

Here is global variables:

HANDLE hFos = m_h;
DEC_DATA* Frame = NULL;
int dataLen = 0;
DECFMT videofmt = DECTYPE_YUYV422;
DECFMT audiofmt = DECTYPE_PCM;
int w=0, h=0;
int mediaSpeed = 0;
Bilityuk gravatar imageBilityuk ( 2016-02-07 11:01:00 -0600 )edit

Function:

if (GetVideoData(hFos, (char**)&Frame, &dataLen, videofmt,&mediaSpeed) )
{
SetMediaSpeed(mediaSpeed);
if (dataLen)
{
w = pFrame->media.video.picWidth;
h = pFrame->media.video.picHeight;
m_ddraw.CreatEmptySurface(Frame->media.video.picWidth, Frame->media.video.picHeight);
m_ddraw.CreatOverlaySurface(Frame->media.video.picWidth, Frame->media.video.picHeight);
HWND hWnd = GetDlgItem(IDC_STATIC_SCREEN)->GetSafeHwnd();
m_d3d.InitDDraw(hWnd, w, h);
}
Mat InImg(h, w,CV_8UC3);  
memcpy(InImg.data,pFrame->data, sizeof(char)*w*h);          
InImg.copyTo(displayedFrame);

//Face Recogition processing//<<-- process the displayedFrame Mat

//display image//
m_d3d.DrawVideoIamge((char*)displayedFrame.data, 1, 0);
}
Bilityuk gravatar imageBilityuk ( 2016-02-07 11:04:50 -0600 )edit

@Bilityuk, rather edit your question, and add further information there, than making multiple comments

(the outcome will be much more readable / useful)

berak gravatar imageberak ( 2016-02-07 11:09:31 -0600 )edit
1

here's the beef :)

DECFMT videofmt = DECTYPE_YUYV422;

berak gravatar imageberak ( 2016-02-07 11:11:42 -0600 )edit

could be the problem. At first I would check (char**)&Frame and try something like &Frame->data

&Frame->data doesnt make any sence in compare with Frame->data The same result.

Bilityuk gravatar imageBilityuk ( 2016-02-07 11:19:33 -0600 )edit

berak, can you explaine please wich way to dig? DECFMT has the following types:

typedef enum  
{
DECTYPE_VIDEORAW,
DECTYPE_ARGB32,   //packed ARGB 8:8:8:8, 32bpp, ARGBARGB...
DECTYPE_RGBA32,    //packed RGBA 8:8:8:8, 32bpp, RGBARGBA...
DECTYPE_ABGR32,    //packed ABGR 8:8:8:8, 32bpp, ABGRABGR...
DECTYPE_BGRA32,    //packed BGRA 8:8:8:8, 32bpp, BGRABGRA...
DECTYPE_RGB24,    //packed RGB 8:8:8, 24bpp, RGBRGB...
DECTYPE_BGR24,     //packed RGB 8:8:8, 24bpp, BGRBGR...
DECTYPE_RGB565BE,  //packed RGB 5:6:5, 16bpp, (msb)   5R 6G 5B(lsb), big-endian
DECTYPE_RGB565LE,  //packed RGB 5:6:5, 16bpp, (msb)   5R 6G 5B(lsb), little-endian
DECTYPE_BGR565BE,  //packed BGR 5:6:5, 16bpp, (msb)   5B 6G 5R(lsb), big-endian
DECTYPE_BGR565LE,  //packed BGR 5:6:5, 16bpp
Bilityuk gravatar imageBilityuk ( 2016-02-07 11:25:06 -0600 )edit

Here is the rest of the enum:

DECTYPE_YUV420,
DECTYPE_YUYV422,
DECTYPE_UYVY422,
DECTYPE_H264,
DECTYPE_MJPEG,  
DECTYPE_MJPEG_BASE64,
DECTYPE_H264_BASE64,        
DECTYPE_AUDIORAW,
DECTYPE_G726,
DECTYPE_G711U,
DECTYPE_PCM,
DECTYPE_ADPCM,
DECTYPE_G711A,
DECTYPE_AAC,
}DECFMT;
Bilityuk gravatar imageBilityuk ( 2016-02-07 11:26:43 -0600 )edit

I don't think copying to a Mat is your problem, but getting the right data. When I look at the Frame struct, I see that there's more than just the data container. So I think GetVideoData(hwnd, (char)&Frame, &dataLen, videofmt,&mediaSpeed); could be the problem. At first I would check (char)&Frame and try something like &Frame->data

I am sure that

GetVideoData(hwnd, (char**)&Frame, &dataLen, videofmt,&mediaSpeed);

is not a problem, because it works perfect and if i pass the native Frame->data to the renderer it draws the video even with 30 fps without a problems..

m_d3d.DrawVideoIamge(Frame->data, 1, 0);

But when i am trying to pass the processed Mat to renderer there is a problem:

m_d3d.DrawVideoIamge((char*)displayedFrame.data, 1, 0);
Bilityuk gravatar imageBilityuk ( 2016-02-07 11:48:50 -0600 )edit

I feel that the problem somewhere in (char*)displayedFrame.data. I think that the renderer doesnt recognize it as native Frame->data format that is of type char data[0];

Bilityuk gravatar imageBilityuk ( 2016-02-07 11:52:04 -0600 )edit

The second part of the problem is in:

Mat InImg(h, w,CV_8UC1);  
memcpy(InImg.data,Frame->data, sizeof(char)*w*h);           
InImg.copyTo(displayedFrame);

Becase i think it is not properly copy the char* data from Frame to Mat, maybe it requires some decoding i have no idea. If i put the displayedFrame to imshow() just after i memcpy() it to Mat it will not be drawn properly.

Bilityuk gravatar imageBilityuk ( 2016-02-07 11:58:23 -0600 )edit

The broblem is clear for now. How to convert BGR24 to YUYV422 that i can draw it with DrawVideoImage function? Wich CV_8U option to use (CV_8UC1,CV_8UC2,CV_8UC3,CV_8UC4) and wich option to use for cv::CvtColor(dst,src, ????).

Bilityuk gravatar imageBilityuk ( 2016-02-07 22:57:23 -0600 )edit

Can anybody share a working pixel convertion function. I cant find the right solution fo my problem..

Bilityuk gravatar imageBilityuk ( 2016-02-08 05:16:02 -0600 )edit