Android OpenCV应用程序的内存问题

时间:2018-01-11 21:52:01

标签: android c++ opencv memory

我想加载5张图片并将它们转换为Mat浮点数以进行openCV处理。我顺便使用Android NDK,这是代码的C ++部分。

我的代码在Android模拟器上运行正常,但在我的设备上进行测试时,它会在浮动转换时停止(标记如下),这让我觉得它是一个内存问题。

我很擅长使用Android管理内存,所以我想知道我是如何解决这个问题的。

//Obtain training image 1
AAsset *trainOne = AAssetManager_open(mgr, "1.JPG", AASSET_MODE_UNKNOWN);
long sizeOfTrainOne = AAsset_getLength(trainOne);
char *bufferTrainOne = (char *) AAsset_getBuffer(trainOne);
std::vector<char> trainOneData(bufferTrainOne, bufferTrainOne + sizeOfTrainOne);
cv::Mat trainOneMat = cv::imdecode(trainOneData, IMREAD_UNCHANGED);

//Obtain training image 2
AAsset *trainTwo = AAssetManager_open(mgr, "2.JPG", AASSET_MODE_UNKNOWN);
long sizeOfTrainTwo = AAsset_getLength(trainTwo);
char *bufferTrainTwo = (char *) AAsset_getBuffer(trainTwo);
std::vector<char> trainTwoData(bufferTrainTwo, bufferTrainTwo + sizeOfTrainTwo);
cv::Mat trainTwoMat = cv::imdecode(trainTwoData, IMREAD_UNCHANGED);

//Obtain training image 3
AAsset *trainThree = AAssetManager_open(mgr, "3.JPG", AASSET_MODE_UNKNOWN);
long sizeOfTrainThree = AAsset_getLength(trainThree);
char *bufferTrainThree = (char *) AAsset_getBuffer(trainThree);
std::vector<char> trainThreeData(bufferTrainThree, bufferTrainThree + sizeOfTrainThree);
cv::Mat trainThreeMat = cv::imdecode(trainThreeData, IMREAD_UNCHANGED);

//Obtain training image 4
AAsset *trainFour = AAssetManager_open(mgr, "c1.JPG", AASSET_MODE_UNKNOWN);
long sizeOfTrainFour = AAsset_getLength(trainFour);
char *bufferTrainFour = (char *) AAsset_getBuffer(trainFour);
std::vector<char> trainFourData(bufferTrainFour, bufferTrainFour + sizeOfTrainFour);
cv::Mat trainFourMat = cv::imdecode(trainFourData, IMREAD_UNCHANGED);

//Obtain training image 5 
AAsset *trainFive = AAssetManager_open(mgr, "c2.JPG", AASSET_MODE_UNKNOWN);
long sizeOfTrainFive = AAsset_getLength(trainFive);
char *bufferTrainFive = (char *) AAsset_getBuffer(trainFive);
std::vector<char> trainFiveData(bufferTrainFive, bufferTrainFive + sizeOfTrainFive);
cv::Mat trainFiveMat = cv::imdecode(trainFiveData, IMREAD_UNCHANGED);

//Change all mats into floats
cv::Mat float1;
cv::Mat float2;
cv::Mat float3;
cv::Mat float4;
cv::Mat float5;

trainOneMat.convertTo(float1, CV_32FC1);
trainTwoMat.convertTo(float2, CV_32FC1);  <--------- stops here
trainThreeMat.convertTo(float3, CV_32FC1);
trainFourMat.convertTo(float4, CV_32FC1);
trainFiveMat.convertTo(float5, CV_32FC1);

//Combine into training Mat
train_data.push_back(float1.reshape(1, 1));
train_data.push_back(float2.reshape(1, 1));
train_data.push_back(float3.reshape(1, 1));
train_data.push_back(float4.reshape(1, 1));
train_data.push_back(float5.reshape(1, 1));

float labelOne = 1;
float labelTwo = 1;
float labelThree = 1;
float labelFour = 2;
float labelFive = 2;

train_label.push_back(labelOne);
train_label.push_back(labelTwo);
train_label.push_back(labelThree);
train_label.push_back(labelFour);
train_label.push_back(labelFive);

knn->train(train_data, ml::ROW_SAMPLE, train_label); <-------

jintArray resultImage;
return resultImage;

1 个答案:

答案 0 :(得分:0)

关于在这种情况下你唯一能做的就是处理系列操作,即完全加载训练集1,处理它然后释放源数据,然后对剩余数据执行相同的操作。如果内存实际上足够紧,以至于您无法将内存中的数据保存在内存中,那么您就不必尝试这样做。

另请注意,AAssetManager_open调用创建的对象会泄露。

你可以连续完成*之类的测试*:

char const & sourceImages[] {"1.JPG", "2.JPG", "3.JPG", "4.JPG", "5.JPG"};
cv::Mat float[5];
for(size_t ndx = 0; 5>ndx; ++ndx)
{
  AAsset * trainOne = AAssetManager_open(mgr, "1.JPG", AASSET_MODE_UNKNOWN);
  long sizeOfTrainOne = AAsset_getLength(trainOne);
  char *bufferTrainOne = (char *) AAsset_getBuffer(trainOne);

  std::vector<char> trainOneData(bufferTrainOne, bufferTrainOne + sizeOfTrainOne);
  cv::Mat trainMat = cv::imdecode(trainOneData, IMREAD_UNCHANGED);
  trainMat.convertTo(float[ndx], CV_32FC1);
}