C++ OpenCV/C-提高耗时循环的速度?
我最近使用OpenCV 2.31(C++)实现了一种图像扭曲方法。但是, 方法非常耗时。。。经过一些调查和改进 我成功地将处理时间从400ms减少到120ms左右,这非常好。 我通过展开循环来实现这个结果(它将时间从400毫秒减少到330毫秒) 然后,我在我的VC++编译器2008 express edition(enabled O2 flag)上启用了优化标志——最后一次修复将处理时间提高到了120毫秒左右 然而,由于我有一些其他的处理来实现这个扭曲,我想把这个处理时间减少到20毫秒,当然,低于这个值会更好,但我不知道这是否可能 还有一件事,我想使用免费提供的库来完成。 所有建议都非常受欢迎 贝娄,你会找到我说的方法 谢谢你的帮助 阿里尔BC++ OpenCV/C-提高耗时循环的速度?,c++,opencv,C++,Opencv,我最近使用OpenCV 2.31(C++)实现了一种图像扭曲方法。但是, 方法非常耗时。。。经过一些调查和改进 我成功地将处理时间从400ms减少到120ms左右,这非常好。 我通过展开循环来实现这个结果(它将时间从400毫秒减少到330毫秒) 然后,我在我的VC++编译器2008 express edition(enabled O2 flag)上启用了优化标志——最后一次修复将处理时间提高到了120毫秒左右 然而,由于我有一些其他的处理来实现这个扭曲,我想把这个处理时间减少到20毫秒,当然,低
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;
}
cv::Mat-Warp::分段扭曲(常数cv::Mat&isosource,常数cv::Mat&s,类型转换类型)
{
cv::Mat Idest(roi.height,roi.width,isosource.type(),cv::Scalar::all(0));
浮动席,XJ,XK,YI,YJ,YK,X,Y;
浮点数X2X1、Y2Y1、X2X、Y2Y、XX1、YY1、X2X1_Y2Y1、a1、a2、a3、a4、b1、b2、c1、c2;
int-x1,y1,x2,y2;
chark;
int nc=roi.width;
int nr=roi高度;
int channels=isosource.channels();
int N=nr*nc;
浮点*alphaPtr=alpha.ptr(0);
浮点*betaPtr=beta.ptr(0);
char*triMaskPtr=triMask.ptr(0);
uchar*IdestPtr=Idest.data;
对于(int i=0;i
我建议:
1.将公因数除法改为乘法。
i、 e.从a开始=a1/d;b=b1/d至d_1=1/d;a=a1*d_1;b=b1*d_1
2.将四个if测试消除为单个双线性插值
我不确定这是否对你有帮助。您可以试一试。为什么不喜欢OpenCV的Waspring函数?嗨,Andrey-您肯定是指cv::warpAffine()函数-对吧?嗨,Andrey-
cv::warpAffine()
函数不符合我的需要,因为它正在对整个图像进行扭曲。我的方法是使用delaunay网格(上面函数中的cv::Mat&s)只使用图像的一部分进行分段扭曲。。。这没有多大帮助。无论如何,谢谢你。