Basically, I am trying to read a live feed from a webcam, split this feed into a grid of 10x10 (100 total) blocks and re-build the video frame in a random order. With this new order of blocks making up a frame I am trying to apply effects to each block depending on its position (for example: greyscale, gausian blur etc). The above is okay. The problem I am experiencing is coming from trying to rebuild the frame with blocks which are both RGB and greyscale being that one has three channels the other has one, giving the following error:
error: (-215) channels() == CV_MAT_CN(dtype) in function copyTo
I've encountered this situation before and in the past have resolved it by duplicating the single grey-scale channel three times and merging together. This time round however it doesn't seem to be solving the problem. I should also point out I am quite new to OpenCV so I could be confusing something trivial. I expect the problem is in the second case of the switch statement:
#include <imgproc_c.h>
#include <iostream>
using namespace cv;
int main( int argc, char** argv ) {
namedWindow( "Example2_10", WINDOW_AUTOSIZE );
VideoCapture cap;
if (argc==1) {
cap.open(-1); //0
} else {
cap.open(argv[1]);
}
if( !cap.isOpened() ) { // check if we succeeded
std::cerr << "Couldn't open capture." << std::endl;
return -1;
}
int frameWidth = cap.get(CV_CAP_PROP_FRAME_WIDTH);
int frameHeight = cap.get(CV_CAP_PROP_FRAME_HEIGHT);
cv::Size sb_size(frameWidth/10, frameHeight/10);
Mat frame, img_gry, img_gry_color, img_cny_color, img_cny, img_join, img_flip, temp, img_effect;
vector<Mat> img_gry_vec;
vector<Mat> img_cny_vec;
int n_cols = 10;
int n_rows = 10;
//Create multidimensional array of key pair values for positional data
std::pair<int, int> posIndex[100];
//Populate positional array with positions of every possible frame block
int counter = 0;
for(int i = 0; i < frameWidth; i += sb_size.width){
for(int j = 0; j < frameHeight; j += sb_size.height){
posIndex[counter] = std::make_pair(i, j);
counter++;
}
}
//Random shuffle positional array so as to provide random structure for compilation
std::random_shuffle(&posIndex[0], &posIndex[100]);
for(;;) {
cap >> frame;
if( frame.empty() )
break;
//Create empty grid to be populated with blocks
Mat3b grid(n_rows * sb_size.height, n_cols * sb_size.width, Vec3b(0,0,0));
//Initialise row/column and effect counters.
int rowCounter = 0;
int colCounter = 0;
int blockIndex = 0;
int effectIndex = 0;
for(int i = 0; i < frameWidth; i += sb_size.width){//iterate columns
colCounter = 0; //Reset column number on new row
rowCounter++; //Count row number
effectIndex++; //reset effect counter to equal row number on new row.
if(effectIndex == 6){
effectIndex = 1;
}
for(int j = 0; j < frameHeight; j += sb_size.height){//iterate rows
colCounter++; //Count column number: 0 - 9
blockIndex++; //Count block index: 0 - 99
//Get block position from shuffled positional array to temporary storage.
temp = Mat(frame, Rect(posIndex[blockIndex].first, posIndex[blockIndex].second, sb_size.width, sb_size.height)).clone();
Rect roi(i, j, sb_size.width, sb_size.height);//Get region of interest
effectIndex++;
//if effect index reaches five, reset to one
if(effectIndex == 6){
effectIndex = 1;
}
//Determine which effect to apply based on effect index
switch(effectIndex){
case 1:
//Copy to grid at correct roi with no effect applied.
temp.copyTo(grid(roi));
break;
case 2:
cvtColor(temp, img_gry, COLOR_BGR2GRAY);
img_gry_vec.push_back(img_gry);
img_gry_vec.push_back(img_gry);
img_gry_vec.push_back(img_gry);
cv::merge(img_gry_vec, img_gry_color);
img_gry_color.copyTo(grid(roi));
break;
case 3:
temp.copyTo(grid(roi));
break;
case 4:
GaussianBlur( temp, img_effect, Size(5, 5), 3, 3 );
img_effect.copyTo(grid(roi));
break;
case 5:
temp.copyTo(grid(roi));
break;
}
}
}
imshow( "Example3", grid);
img_gry_vec.clear();
if( cv::waitKey(33) >= 0 )
break;
}
return 0;
}
The program runs as expected without the greyscale applied. Any help or pointers is much appreciated.