Android Opencv应用程序慢得令人痛苦,我该怎么办?
我有一个人脸识别应用程序,它运行良好,在s6 egde上的速度为15+fps。现在,当我添加一些代码来确定眼睛中心时(特别是),速度降到了0.01 fps。我卡住了。Android Studio monitor表示cpu使用率约为15%,内存为20MB,分辨率约为400*300。 下面是我用来实现查找眼睛中心算法的代码(翻译自c++):Android Opencv应用程序慢得令人痛苦,我该怎么办?,android,performance,opencv,Android,Performance,Opencv,我有一个人脸识别应用程序,它运行良好,在s6 egde上的速度为15+fps。现在,当我添加一些代码来确定眼睛中心时(特别是),速度降到了0.01 fps。我卡住了。Android Studio monitor表示cpu使用率约为15%,内存为20MB,分辨率约为400*300。 下面是我用来实现查找眼睛中心算法的代码(翻译自c++): public class TimmAlgorithm { Point unscalePoint(Point p, Rect origSize) {
public class TimmAlgorithm {
Point unscalePoint(Point p, Rect origSize) {
float ratio = (((float) kFastEyeWidth)/origSize.width);
int x = (int)Math.round(p.x / ratio);
int y = (int)Math.round(p.y / ratio);
return new Point(x,y);
}
Mat scaleToFastSize( Mat src,Mat dst) {
Imgproc.resize(src, dst, new Size(kFastEyeWidth,(((float)kFastEyeWidth)/src.size().width) * src.size().height));
return dst;
}
Mat computeMatXGradient(Mat mat) {
Mat out=new Mat(mat.size(), CvType.CV_64F);
for (int y = 0; y < mat.size().height; ++y) {
out.put(y,0, (mat.get(y,1)[0]-mat.get(y,0)[0]));
for (int x = 1; x < mat.size().width - 1; ++x) {
out.put(y,x,mat.get(y,x+1)[0]-(mat.get(y,x-1)[0]/2));
}
out.put(y,(int)mat.size().width-1,mat.get(y,(int)mat.size().width-1)[0]-mat.get(y,(int)mat.size().width-2)[0]);
}
return out;
}
Mat testPossibleCentersFormula(int x, int y, Mat weight,double gx, double gy, Mat out) {
// for all possible centers
for (int cy = 0; cy < out.size().height; ++cy) {
for (int cx = 0; cx < out.size().width; ++cx) {
if (x == cx && y == cy) {
continue;
}
// create a vector from the possible center to the gradient origin
double dx = x - cx;
double dy = y - cy;
// normalize d
double magnitude = Math.sqrt((dx * dx) + (dy * dy));
dx = dx / magnitude;
dy = dy / magnitude;
double dotProduct = dx*gx + dy*gy;
dotProduct = Math.max(0.0,dotProduct);
// square and multiply by the weight
if (kEnableWeight) {
out.put(cy,cx,out.get(cy,cx)[0] + dotProduct * dotProduct * (weight.get(cy,cx)[0]/kWeightDivisor));
} else {
out.put(cy,cx,out.get(cy,cx)[0]+dotProduct * dotProduct);
}
}
}
return out;
}
Point findEyeCenter(Mat face, Rect eye,Mat debugwindow) {
// Mat eyeROIUnscaled = face.submat(eye);
Mat eyeROI = face.submat(eye);
// Mat eyeROI=new Mat();
// eyeROI=scaleToFastSize(eyeROIUnscaled, eyeROI);
// draw eye region
Imgproc.rectangle(face,eye.tl(),eye.br(),new Scalar(255, 0, 0, 255), 2);
//-- Find the gradient
Mat gradientX = computeMatXGradient(eyeROI);
Mat gradientY = computeMatXGradient(eyeROI.t()).t();
//-- Normalize and threshold the gradient
// compute all the magnitudes
Mat mags = matrixMagnitude(gradientX, gradientY);
//compute the threshold
double gradientThresh = computeDynamicThreshold(mags, kGradientThreshold);
//double gradientThresh = kGradientThreshold;
//double gradientThresh = 0;
//normalize
for (int y = 0; y < eyeROI.size().height; ++y) {
for (int x = 0; x < eyeROI.size().width; ++x) {
double gX = gradientX.get(y,x)[0];
double gY = gradientY.get(y,x)[0];
double magnitude = mags.get(y,x)[0];
if (magnitude > gradientThresh) {
gradientX.put(y,x,gX/magnitude);
gradientY.put(y,x,gY/magnitude);
} else {
gradientX.put(y,x,0.0);
gradientY.put(y,x,0.0);
}
}
}
//-- Create a blurred and inverted image for weighting
Mat weight=new Mat();
Imgproc.GaussianBlur( eyeROI, weight, new Size( kWeightBlurSize, kWeightBlurSize ), 0, 0 );
for (int y = 0; y < weight.size().height; ++y) {
for (int x = 0; x < weight.size().width; ++x) {
weight.put(y,x,255 - weight.get(y,x)[0]);
}
}
//imshow(debugWindow,weight);
//-- Run the algorithm!
Mat outSum = Mat.zeros(eyeROI.size(),CvType.CV_64F);
// for each possible gradient location
// Note: these loops are reversed from the way the paper does them
// it evaluates every possible center for each gradient location instead of
// every possible gradient location for every center.
// printf("Eye Size: %ix%i\n",outSum.cols,outSum.rows);
for (int y = 0; y < weight.size().height; ++y) {
for (int x = 0; x < weight.size().width; ++x) {
double gX = gradientX.get(y,x)[0];
double gY = gradientY.get(y,x)[0];
if (gX == 0.0 && gY == 0.0) {
continue;
}
outSum=testPossibleCentersFormula(x, y, weight, gX, gY, outSum);
}
}
// scale all the values down, basically averaging them
double numGradients = (weight.size().height*weight.size().width);
Mat out=new Mat();
outSum.convertTo(out, CvType.CV_32F,1.0/numGradients);
//imshow(debugWindow,out);
//-- Find the maximum point
Core.MinMaxLocResult minmaxResult=Core.minMaxLoc(out);
Point maxP=minmaxResult.maxLoc;
double maxVal=minmaxResult.maxVal;
//-- Flood fill the edges
if(kEnablePostProcess) {
Mat floodClone=new Mat();
//double floodThresh = computeDynamicThreshold(out, 1.5);
double floodThresh = maxVal * kPostProcessThreshold;
Imgproc.threshold(out, floodClone, floodThresh, 0.0f, Imgproc.THRESH_TOZERO);
if(kPlotVectorField) {
//plotVecField(gradientX, gradientY, floodClone);
// imwrite("eyeFrame.png",eyeROIUnscaled);
}
Mat mask = floodKillEdges(floodClone);
//imshow(debugWindow + " Mask",mask);
out.copyTo(debugwindow);
//imshow(debugWindow,out);
// redo max
minmaxResult=Core.minMaxLoc(out,mask);
maxP=minmaxResult.maxLoc;
maxVal=minmaxResult.maxVal;
}
return maxP;
// return unscalePoint(maxP,eye);
}
boolean floodShouldPushPoint(Point np, Mat mat) {
return inMat(np, (int)mat.size().height, (int)mat.size().width);
}
Mat floodKillEdges(Mat mat) {
Imgproc.rectangle(mat,new Point(0,0),new Point(mat.size().width,mat.size().height),new Scalar(255));
Mat mask=new Mat(mat.size(), CvType.CV_8U, new Scalar(255));
ArrayDeque<Point> toDo=new ArrayDeque();
toDo.add(new Point(0,0));
while (!toDo.isEmpty()) {
Point p = toDo.poll();
if ( mat.get((int)p.x,(int)p.y)[0]==0.0f) {
continue;
}
// add in every direction
Point np=new Point(p.x + 1, p.y); // right
if (floodShouldPushPoint(np, mat)) toDo.push(np);
np.x = p.x - 1; np.y = p.y; // left
if (floodShouldPushPoint(np, mat)) toDo.push(np);
np.x = p.x; np.y = p.y + 1; // down
if (floodShouldPushPoint(np, mat)) toDo.push(np);
np.x = p.x; np.y = p.y - 1; // up
if (floodShouldPushPoint(np, mat)) toDo.push(np);
// kill it
mat.put((int)p.x,(int)p.y,0.0f);
mask.put((int)p.x,(int)p.y,0);
}
return mask;
}
boolean rectInImage(Rect rect, Mat image) {
return rect.x > 0 && rect.y > 0 && rect.x+rect.width < image.size().width &&
rect.y+rect.height < image.size().height;
}
boolean inMat(Point p,int rows,int cols) {
return p.x >= 0 && p.x < cols && p.y >= 0 && p.y < rows;
}
Mat matrixMagnitude(Mat matX, Mat matY) {
Mat mags=new Mat(matX.size(),CvType.CV_64F);
for (int y = 0; y < matX.size().height; ++y) {
for (int x = 0; x < matX.size().width; ++x) {
double gX = matX.get(y,x)[0];
double gY = matY.get(y,x)[0];
double magnitude = Math.sqrt((gX * gX) + (gY * gY));
mags.put(y,x,magnitude);
}
}
return mags;
}
double computeDynamicThreshold(Mat mat, double stdDevFactor) {
MatOfDouble stdMagnGrad=new MatOfDouble();
MatOfDouble meanMagnGrad=new MatOfDouble();
Core.meanStdDev(mat, meanMagnGrad, stdMagnGrad);
double stdDev = stdMagnGrad.get(0,0)[0] / Math.sqrt(mat.size().height*mat.size().width);
return stdDevFactor * stdDev + meanMagnGrad.get(0,0)[0];
}
公共类TimmAlgorithm{
点未缩放点(点p,矩形原点){
浮动比率=((浮动)kFasteyWidth)/origSize.width);
整数x=(整数)数学四舍五入(p.x/比率);
整数y=(整数)数学四舍五入(p.y/比率);
返回新点(x,y);
}
垫板尺寸(垫板src、垫板dst){
Imgproc.resize(src,dst,新大小(kFastEyeWidth,((float)kFastEyeWidth)/src.Size().width)*src.Size().height);
返回dst;
}
Mat计算梯度(Mat Mat){
Mat out=新的Mat(Mat.size(),CvType.CV_64F);
对于(int y=0;y梯度阈值){
梯度x.put(y,x,gX/量级);
梯度放置(y,x,gY/量级);
}否则{
梯度x.put(y,x,0.0);
梯度放置(y,x,0.0);
}
}
}
//--创建模糊和反转图像以进行加权
垫重=新垫();
Imgproc.GaussianBlur(眼睛ROI,重量,新尺寸(kWeightBlurSize,kWeightBlurSize),0,0);
对于(int y=0;y