У меня есть прямоугольное входное изображение размером 256x507, которое я хочу сопоставить с изображением 1920x1080, но в виде сектора.
У меня уже есть написанный код, который делает то, что я хочу:
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;
}
}
}
}
Но этот код медленный. Есть ли способ использовать векторизованные операции numpy для ускорения? Или использование GPU было бы еще лучше.
«использовать векторизованные операции numpy» - этот код выглядит для меня как C++, так как же Numpy здесь уместен?
Если вас беспокоит производительность, вам нужно а) помочь компилятору, б) не повторяться. | Ожидаете ли вы, что pi
изменится во время выполнения? Если нет, то почему const
? Теперь, поскольку pi
является константой, зачем пересчитывать 65*pi/180
дважды для каждого пикселя? Точно так же sin(65*pi/180)
также будет все время одним и тем же, поэтому нет необходимости вычислять его снова и снова. И так далее...
Для деформирования изображения с ускорением на GPU вы можете использовать cv2::cuda::remap . Также прочитайте это обсуждение
Вы не можете использовать функцию warpPolar()
с флагом WARP_INVERSE_MAP
? (Я не знаю о скорости этого.)
Убедитесь, что вы компилируете свою программу с включенной оптимизацией.
Я сгенерировал карту один раз в начале, затем использовал cv::remap. Спасибо всем комментариям
создайте карту один раз, затем используйте remap. Также лучше определите, что означает «медленный»