John Doe John Doe - 26 days ago 15
C++ Question

Shaping image pixel by pixel in OpenCV

So the idea is that I have and image recorded from cylindrical camera through a rectangular window in it. Image we get is a rectangular picture though it must be circular. I'm using OpenCV to move image pixel by pixel, line by line into a circle from a given rectangular picture. Problem is that pixel distribution is uneven depending on a radius. What algorithm you'd suggest to make distribution more even? Here's the code:

int main( int argc, char** argv ) {


Mat src = imread( "srcImg.jpg", 1 );
Mat dst = imread( "dstImg.jpg", 1 );

int srcH = src.rows; int srcW = src.cols;
int dstH = dst.rows; int dstW = src.cols;

//convert chamber radius to pixels
double alpha, alpha_double, alpha_triple;
int r = 1500;
double k = 210 / (500 * PI);
int l = 1;
//take pixels from source and arrange them into circles

for (int i = srcH - 1; i > 0; i--) {
for (int j = 1; j <= srcW ; j++) {
alpha = (double) (2 * PI * (r * k + i)) / j;
alpha_double = (double) (2 * PI * ((r + 15) * k + i)) / j;
alpha_triple = alpha_double = (double) (2 * PI * ((r + 30) * k + i)) / j;

int x_new = abs((int) (dstW / 2 - (r * k + i) * cos(alpha)) - 200);
int y_new = abs((int) (dstH / 2 - (3.5*(r * k + i) * sin(alpha))) + 1000);

int x_new_double = abs((int) (dstW / 2 - (r * k + i) * cos(alpha_double)) - 200);
int y_new_double = abs((int) (dstH / 2 - (3.5*(r * k + i) * sin(alpha_double))) + 1000);

int x_new_triple = abs((int) (dstW / 2 - (r * k + i) * cos(alpha_triple)) - 200);
int y_new_triple = abs((int) (dstH / 2 - (3.5*(r * k + i) * sin(alpha_triple))) + 1000);

dst.at<uchar>(x_new, y_new) = src.at<uchar>(srcH - i, srcW - j);
dst.at<uchar>(x_new_double, y_new_double) = src.at<uchar>(srcH - i, srcW - j);
dst.at<uchar>(x_new_triple, y_new_triple) = src.at<uchar>(srcH - i, srcW - j);
}
}

//make dst image grey and show all images
Mat dstGray;
cvtColor(dst, dstGray, CV_RGB2GRAY);
imshow("Source", src);
imshow("Result", dstGray);

waitKey();
return 0;


And the result

Answer

This is hardly a full answer, but I would try some kind of projection mapping instead of manually accessing every pixel. There must be an openCV way to create a destination shape then say : "Take my original image and make it fit the destination shape"

This is rather trivial for rectangles as you can see here, but your hole in the middle makes it harder.