0

I have a rectangular input image of size 256x507, which I wish to map to a 1920x1080 image but in form of a sector.

  • y of input is proportional to distance in output image
  • x of input is proportional to angle from centre line in output image

I already have a written a code which does what I want:

cv::Mat sector_image=cv::Mat::zeros(1080, 1920, CV_8UC1);
int cx=888;
int cy=1080-949;
int rx=1687;
int ry=1080-575;
int lx=89;
int ly=1080-575;
float r= distance(cx, cy, lx,ly);
 float pi = 2 * asin(1.0);
float src_angl=130*pi/180;
//std::cout<<"angle(lx,ly,cx,cy,rx,ry);"<<angle(lx,ly,cx,cy,rx,ry)<<std::endl;
//std::cout<<"src_angl"<<src_angl<<std::endl;
for (int y = 0; y < sector_image.rows; y += 1)
{
    for (int x = 0; x < sector_image.cols; x += 1)
    {
         float dist=  distance(cx, cy, x,y);
         int px=0;int py=0;
         px=r*(x-cx)/dist + cx;
         py=r*(y-cy)/dist + cy;
         if ((px>=lx)&&(px<=rx)&&(dist<=r)&&(y>=cy)){
            float angl= angle(lx,ly,cx,cy,x,y);
            angl=angl-65*pi/180;
            //std::cout<<"angl"<<angl<<std::endl;
            int srcy = (int)((dist/r)*my_mat.rows);
            int srcx = (int)(sin(angl)/sin(65*pi/180)*128+127.5);
            if(srcx==-1){
                srcx=0;
            }
            else if(srcx==256){
                srcx=255;
            }
            if((srcx>=0)&&(srcy>=0)&&(srcx<=my_mat.cols)&&(srcy<=my_mat.rows))
           {
                sector_image.at<uchar>(y,x) = my_mat.at<uchar>(srcy,srcx);
                //std::cout<<x<<" "<<y<<" "<<angl<<std::endl;

            }


        }
    }
}

But this code is slow. Is there any way to use vectorized numpy operations to speed it up? Or using GPU would be even better.

Markus
  • 5,976
  • 5
  • 6
  • 21
  • 2
    create the map once, then use remap. Also define better what "slow" means – Miki Apr 14 '23 at 12:33
  • "use vectorized numpy operations" -- that code looks like C++ to me, so how is Numpy relevant here? – Dan Mašek Apr 14 '23 at 13:16
  • If you're concerned about performance, then you need to a) help the compiler, b) avoid repeating repeating yourself. | Do you expect `pi` to change during runtime? If not, why is it not `const`? Now, since `pi` is a constant, why recalculate `65*pi/180` *twice* per pixel? Similarly, `sin(65*pi/180)` will also be the same thing all the time, so no need to calculate it over and over. And so on... – Dan Mašek Apr 14 '23 at 13:21
  • For GPU accelerated image warping you can use [cv2::cuda::remap](https://docs.opencv.org/4.x/db/d29/group__cudawarping.html#ga0ece6c76e8efa3171adb8432d842beb0). Please also read [this discussion](https://stackoverflow.com/questions/72828835/why-cvcudaremap-wrong-while-cvremap-right) – Markus Apr 15 '23 at 08:14
  • 1
    Can't you use the function `warpPolar()` with `WARP_INVERSE_MAP` flag? (I don't know about speed of it.) – fana Apr 17 '23 at 01:32
  • Make sure you are compiling your program with optimizations *enabled*. – Jesper Juhl Apr 19 '23 at 09:09

1 Answers1

0

I Generated map once at the start, then used cv::remap. Thanks to all the comments