Chris Mondiek
Chris Mondiek

Reputation: 153

opencv six channel matrix multiply

I am working on a spectral camera and am using opencv to do the processing. I just started using opencv, so this might not be the best way to do this.

Basically this code grabs frames from two video streams then does a matrix multiplication. captureF and captureM are both video streams and eigen is a 6x7 matrix where the last row is an offset that needs subtracted from the image.

I could not figure out how to combine the two frames into one six channel imageII looked at merge and mixchannels but couldn't get either to work), so I wound up doing the matrix multiplication manually and saving the data out to two three channel images, but ideally this would be one 6 channel matrix. My question is that this code currently runs very slow (20sec per frame) and I wondering if there is a way to do this that runs faster and or do this using a 6channel image?

        IplImage imgF = cvQueryFrame(captureF);
        IplImage dst2 = cvQueryFrame(captureM);


        IplImage *OutImg1 = cvCreateImage(cvSize(imgF->width, imgF->height), IPL_DEPTH_32F, 3);
        IplImage *OutImg2 = cvCreateImage(cvSize(imgF->width, imgF->height), IPL_DEPTH_32F, 3);

        // iterates through each frame in the image.
        for(int i=0; i<(imgF->imageSize)/3;i+=3){
                ((float*)OutImg1->imageData)[i] =   cvmGet(eigen,0,2)*(imgF->imageData[i]-cvmGet(eigen,6,2)) + cvmGet(eigen,0,1)*(imgF->imageData[i+1]-cvmGet(eigen,6,1)) + cvmGet(eigen,0,0)*(imgF->imageData[i+2]-cvmGet(eigen,6,0)) + cvmGet(eigen,0,5)*(dst2->imageData[i]-cvmGet(eigen,6,5)) + cvmGet(eigen,0,4)*(dst2->imageData[i+1]-cvmGet(eigen,6,4)) + cvmGet(eigen,0,3)*(dst2->imageData[i+2]-cvmGet(eigen,6,3));
                ((float*)OutImg1->imageData)[i+1] = cvmGet(eigen,1,2)*(imgF->imageData[i]-cvmGet(eigen,6,2)) + cvmGet(eigen,1,1)*(imgF->imageData[i+1]-cvmGet(eigen,6,1)) + cvmGet(eigen,1,0)*(imgF->imageData[i+2]-cvmGet(eigen,6,0)) + cvmGet(eigen,1,5)*(dst2->imageData[i]-cvmGet(eigen,6,5)) + cvmGet(eigen,1,4)*(dst2->imageData[i+1]-cvmGet(eigen,0,4)) + cvmGet(eigen,1,3)*(dst2->imageData[i+2]-cvmGet(eigen,6,3));
                ((float*)OutImg1->imageData)[i+2] = cvmGet(eigen,2,2)*(imgF->imageData[i]-cvmGet(eigen,6,2)) + cvmGet(eigen,2,1)*(imgF->imageData[i+1]-cvmGet(eigen,6,1)) + cvmGet(eigen,2,0)*(imgF->imageData[i+2]-cvmGet(eigen,6,0)) + cvmGet(eigen,2,5)*(dst2->imageData[i]-cvmGet(eigen,6,5)) + cvmGet(eigen,2,4)*(dst2->imageData[i+1]-cvmGet(eigen,0,4)) + cvmGet(eigen,2,3)*(dst2->imageData[i+2]-cvmGet(eigen,6,3));

                ((float*)OutImg2->imageData)[i] =   cvmGet(eigen,3,2)*(imgF->imageData[i]-cvmGet(eigen,6,2)) + cvmGet(eigen,3,1)*(imgF->imageData[i+1]-cvmGet(eigen,6,1)) + cvmGet(eigen,3,0)*(imgF->imageData[i+2]-cvmGet(eigen,6,0)) + cvmGet(eigen,3,5)*(dst2->imageData[i]-cvmGet(eigen,6,5)) + cvmGet(eigen,3,4)*(dst2->imageData[i+1]-cvmGet(eigen,0,4)) + cvmGet(eigen,3,3)*(dst2->imageData[i+2]-cvmGet(eigen,6,3));
                ((float*)OutImg2->imageData)[i+1] = cvmGet(eigen,4,2)*(imgF->imageData[i]-cvmGet(eigen,6,2)) + cvmGet(eigen,4,1)*(imgF->imageData[i+1]-cvmGet(eigen,6,1)) + cvmGet(eigen,4,0)*(imgF->imageData[i+2]-cvmGet(eigen,6,0)) + cvmGet(eigen,4,5)*(dst2->imageData[i]-cvmGet(eigen,6,5)) + cvmGet(eigen,4,4)*(dst2->imageData[i+1]-cvmGet(eigen,0,4)) + cvmGet(eigen,4,3)*(dst2->imageData[i+2]-cvmGet(eigen,6,3));
                ((float*)OutImg2->imageData)[i+2] = cvmGet(eigen,5,2)*(imgF->imageData[i]-cvmGet(eigen,6,2)) + cvmGet(eigen,5,1)*(imgF->imageData[i+1]-cvmGet(eigen,6,1)) + cvmGet(eigen,5,0)*(imgF->imageData[i+2]-cvmGet(eigen,6,0)) + cvmGet(eigen,5,5)*(dst2->imageData[i]-cvmGet(eigen,6,5)) + cvmGet(eigen,5,4)*(dst2->imageData[i+1]-cvmGet(eigen,0,4)) + cvmGet(eigen,5,3)*(dst2->imageData[i+2]-cvmGet(eigen,6,3));
        }

Upvotes: 0

Views: 1138

Answers (1)

Bobbi Bennett
Bobbi Bennett

Reputation: 1646

I use opencv2, and am a rank novice so maybe there are better ways. I imagine you can transpose to the old cv if you need too. First, it looks annoyingly like there are not 6 channel Scalars. So convert your data to a NX6 array (N = rows*cols), and use matrix multiply.

Mat twoIm[2];
Mat eigen(6,6,CV_32F);
Mat bigGuy,newGuy;

merge(twoIm,2,bigGuy);            // load your two images into twoIm[0] & twoIm[1]
bigGuy.convertTo(bigGuy, CV_32F); // mat multiply wants everything the same type

Mat bigGal = bigGuy.reshape(1, 6); // this makes 6 channels into 6 rows

newGuy = bigGal.t() * eigen;       // and voila!

Upvotes: 0

Related Questions