c++ - OpenCV/C - 提高耗时循环的速度?

标签 c++ opencv

我最近使用 OpenCV 2.31(C++) 实现了一种图像变形方法。然而,这 方法比较费时间...经过一番调查和改进 我成功地将处理时间从 400 毫秒减少到大约 120 毫秒,这非常好。 我通过展开循环实现了这个结果(它将时间从 400 毫秒减少到 330 毫秒) 然后我在我的 VC++ 编译器 2008 速成版上启用了优化标志(启用 O2 标志)——最后的修复将处理时间提高到大约 120 毫秒。

但是,由于我有一些其他处理要围绕这个 warp 实现,我想将这个处理时间减少到 20 毫秒——当然低于这个值会更好,但我不知道它是否是可能!!!...

还有一件事,我想使用免费提供的库来做到这一点。 我们非常欢迎所有建议。

下面,你会找到我所说的方法。

谢谢你的帮助

爱丽儿 B.

cv::Mat Warp::pieceWiseWarp(const cv::Mat &Isource, const cv::Mat &s, TYPE_CONVERSION type)
{       
cv::Mat Idest(roi.height,roi.width,Isource.type(),cv::Scalar::all(0));
float xi, xj, xk, yi, yj, yk, x, y;
float X2X1,Y2Y1,X2X,Y2Y,XX1,YY1,X2X1_Y2Y1,a1, a2, a3, a4,b1,b2,c1,c2;
int x1, y1, x2, y2;
char k;     
int nc = roi.width;
int nr = roi.height;
int channels = Isource.channels();
int N = nr * nc;


float *alphaPtr = alpha.ptr<float>(0);
float *betaPtr = beta.ptr<float>(0);
char *triMaskPtr = triMask.ptr<char>(0);
uchar *IdestPtr = Idest.data;


for(int i = 0; i < N;  i++, IdestPtr += channels - 1)       
        if((k = triMaskPtr[i]) != -1)// the pixel do belong to delaunay
        {

            cv::Vec3b t = trianglesMap.row(k);

            xi = s.col(1).at<float>(t[0]); yi = s.col(0).at<float>(t[0]); 
            xj = s.col(1).at<float>(t[1]); yj = s.col(0).at<float>(t[1]); 
            xk = s.col(1).at<float>(t[2]); yk = s.col(0).at<float>(t[2]);                       

            x = xi + alphaPtr[i]*(xj - xi) + betaPtr[i]*(xk - xi);
            y = yi + alphaPtr[i]*(yj - yi) + betaPtr[i]*(yk - yi);


            //...some bounds checking here...

            x2 = ceil(x); x1 = floor(x);
            y2 = ceil(y); y1 = floor(y);                

            //2. use bilinear interpolation on the pixel location - see wiki for formula...
            //...3. copy the resulting intensity (GL) to the destination (i,j)

            X2X1 = (x2 - x1);
            Y2Y1 = (y2 - y1);
            X2X  = (x2 - x);
            Y2Y  = (y2 - y);
            XX1  = (x - x1);                
            YY1  = (y - y1);

            X2X1_Y2Y1 = X2X1*Y2Y1;
            a1 = (X2X*Y2Y)/(X2X1_Y2Y1);
            a2 = (XX1*Y2Y)/(X2X1_Y2Y1);
            a3 = (X2X*YY1)/(X2X1_Y2Y1);
            a4 = (XX1*YY1)/(X2X1_Y2Y1);

            b1 = (X2X/X2X1);
            b2 = (XX1/X2X1);

            c1 = (Y2Y/Y2Y1);
            c2 = (YY1/Y2Y1);

            for(int c = 0; c < channels; c++)// Consider implementing this bilinear interpolation elsewhere in another function 
            {
                if(x1 != x2 && y1 != y2)
                    IdestPtr[i + c] = Isource.at<cv::Vec3b>(y1,x1)[c]*a1
                                                + Isource.at<cv::Vec3b>(y2,x1)[c]*a2
                                                + Isource.at<cv::Vec3b>(y1,x2)[c]*a3
                                                + Isource.at<cv::Vec3b>(y2,x2)[c]*a4;                       
                if(x1 == x2 && y1 == y2)
                    IdestPtr[i + c] = Isource.at<cv::Vec3b>(y1,x1)[c];

                if(x1 != x2 && y1 == y2)
                    IdestPtr[i + c] = Isource.at<cv::Vec3b>(y1,x1)[c]*b1 + Isource.at<cv::Vec3b>(y1,x2)[c]*b2;

                if(x1 == x2 && y1 != y2)
                    IdestPtr[i + c] = Isource.at<cv::Vec3b>(y1,x1)[c]*c1 + Isource.at<cv::Vec3b>(y2,x1)[c]*c2;                      
            }                       
        }

if(type == CONVERT_TO_CV_32FC3)
    Idest.convertTo(Idest,CV_32FC3);
if(type == NORMALIZE_TO_1)
    Idest.convertTo(Idest,CV_32FC3,1/255.);
return Idest;
}

最佳答案

我建议:

1.将公因数除法改为乘法。 即从 a = a1/d; b = b1/d 到 d_1 = 1/d; a = a1*d_1; b = b1*d_1

2.消除对单个双线性插值的四个if测试。

我不确定这是否对您有帮助。你可以试试看。

关于c++ - OpenCV/C - 提高耗时循环的速度?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13440096/

相关文章:

C++函数返回函数

c++ - 删除链表中的节点不起作用?

c++ - 当将值复制到现有对象中时,(N)RVO 是否也会发生?

c++ - 填充与矩形相交的蒙版轮廓

python-3.x - 为什么向图像添加高斯噪声会产生白屏?

opencv - OpenCV CAMSHIFT 使用什么样的直方图,是比率还是加权?

c++ - 强制打印到终端(正在传输 std::cout)

c++ - Ubuntu + qt,如何更新?

c++ - 如何将文本放入 OpenCV 中的边界框?

python - 轮廓中的质心(Python、OpenCV)