Ask Your Question
0

Loading two Mats into split short arrays?

asked 2018-11-15 06:34:33 -0600

antithing gravatar image

updated 2018-11-15 07:30:26 -0600

I am trying to replace an existing function with openCv for image handling. This is the function:

ImageBMP::ImageBMP(char * filename) {
    this->filename = filename;
    this->height = 0;
    this->width = 0;
    this->valid = 1;
    this->datapos = -1;
    this->file = nullptr;
}

    ImageBMP* fg = new ImageBMP("test2.bmp");
    ImageBMP* bg = new ImageBMP("back.bmp");

short* fgbgR = new short[size];
    short* fgbgG = new short[size];
    short* fgbgB = new short[size];


    pos = fg->datapos;
    int mx = 3 * fg->width;
    switch (mx % 4)
    {
    case 1:
        mx = mx + 3;
        break;
    case 2:
        mx = mx + 2;
        break;
    case 3:
        mx = mx + 1;
        break;
    }

    std::cout << pos << std::endl;


    // Fill matrix for Foreground and Background
    int i = 0;
    int j = 0;
    for (i = 0; i < fg->height; i++) {
        fseek(fg->file, pos, SEEK_SET);
        fseek(bg->file, pos, SEEK_SET);

        for (j = pos; j < (fg->width + pos); j++) {

            char b = getc(fg->file);
            char g = getc(fg->file);
            char r = getc(fg->file);
            char b_bg = getc(bg->file);
            char g_bg = getc(bg->file);
            char r_bg = getc(bg->file);

            char * tmp = (char*)&fgbgR[i * fg->width + (j - pos)];
            *tmp = r;
            tmp++;
            *tmp = r_bg;

            tmp = (char*)&fgbgG[i * fg->width + (j - pos)];
            *tmp = g;
            tmp++;
            *tmp = g_bg;

            tmp = (char*)&fgbgB[i * fg->width + (j - pos)];
            *tmp = b;
            tmp++;
            *tmp = b_bg;

        }
        pos = mx + pos;

    }

I have tried to swap out the image handling, and so far I have:

cv::Mat imageFG = cv::imread("test2.bmp", -1);
    cv::Mat imageBG = cv::imread("back.bmp", -1);

    //split into channels
    cv::Mat bgr[3];   //destination array
    cv::split(imageFG, bgr);//split source  

    cv::Mat bgrBG[3];   //destination array
    cv::split(imageBG, bgrBG);//split source  

    int sizeCv = imageFG.cols * imageFG.rows;


    short* fgbgRcv = new short[sizeCv];
    short* fgbgGcv = new short[sizeCv];
    short* fgbgBcv = new short[sizeCv];

for (i = 0; i < sizeCv; i++) {


        char b = bgr[0].data[i];
        char g = bgr[1].data[i];
        char r = bgr[2].data[i];
        char b_bg = bgrBG[0].data[i];
        char g_bg = bgrBG[1].data[i];
        char r_bg = bgrBG[2].data[i];

        char * tmp = (char*)&fgbgRcv[i];
        *tmp = r;
        tmp++;
        *tmp = r_bg;

        tmp = (char*)&fgbgGcv[i];
        *tmp = g;
        tmp++;
        *tmp = g_bg;

        tmp = (char*)&fgbgBcv[i];
        *tmp = b;
        tmp++;
        *tmp = b_bg;

    }

Then later, I need to recreate the Mat from a buffer, which i am doing like this:

//back to cv::Mat
    unsigned char* compBuffer = new unsigned char[imageFG.cols * imageFG.rows * imageFG.channels()]; 

    int r = 0;
    int g = 1;
    int b = 2;
    for (int i = 0; i < size; i++)
    {           
        compBuffer[b] = outRGB[i].r;
        compBuffer[g] = outRGB[i].g;
        compBuffer[r] = outRGB[i].b;

        r += 3;
        b += 3;
        g += 3;     
    }

    cv::Mat outMat = cv::Mat(imageFG.rows, imageFG.cols, CV_8UC3, compBuffer);

Is this the fastest way to copy this data around to and from Mat? or is there a better way?

edit retag flag offensive close merge delete

Comments

what are you trying to achieve here ? what is the context ?

berak gravatar imageberak ( 2018-11-15 06:40:03 -0600 )edit

Hi, thanks for getting back to me. I am trying to replace the // Fill matrix for Foreground and Backgroundsection above. What it seems to be doing is combining the two sets of image data. I should probably try to understand what it is doing a bit better before i try to re-code it really!

antithing gravatar imageantithing ( 2018-11-15 06:48:47 -0600 )edit

no, try to explain better, please !

combining the two sets of image data

what does it mean, exactly ?

most likely, what you want, can (and should !) be done without writing ANY loops.

also, are you sure, your images are both 16bit 3 channel ?

berak gravatar imageberak ( 2018-11-15 06:53:03 -0600 )edit

I am trying to understand the function, but am confused here char * tmp = (char*)&fgbgR[i * fg->width + (j - pos)]; it looks like he makes a short[] then assigns the data from both images to it.

antithing gravatar imageantithing ( 2018-11-15 07:14:56 -0600 )edit

yea, but why ?

berak gravatar imageberak ( 2018-11-15 07:19:58 -0600 )edit
1

It is passed into a cuda chroma keying function, which spits out the composited image. I have it working now, will update the question. is this possible without the loops? Thanks again for your patience!

antithing gravatar imageantithing ( 2018-11-15 07:28:41 -0600 )edit

1 answer

Sort by ยป oldest newest most voted
0

answered 2018-11-16 02:29:05 -0600

berak gravatar image

updated 2018-11-16 05:02:55 -0600

no idea, if it really fits your situation, but an easy way to "splice" 2 8bit images into a 16bit one would be:

// our input:
Mat A(h,w,CV_8U);
Mat B(h,w,CV_8U);

now assuming, we want A as the "low nibble", and B as the "high nibble":

// if you think in bits, below is:
// 00000000AAAAAAAA
A.convertTo(A, CV_16U);

// BBBBBBBB00000000
B.convertTo(B, CV_16U, 256); // shift 8 bits to the left

// BBBBBBBBAAAAAAAA
Mat C = A + B;
edit flag offensive delete link more

Question Tools

1 follower

Stats

Asked: 2018-11-15 06:34:33 -0600

Seen: 244 times

Last updated: Nov 16 '18