Home Memory issue with Android OpenCV application
Reply: 1

Memory issue with Android OpenCV application

Ber12345
1#
Ber12345 Published in 2018-01-11 21:52:01Z

I want to load 5 images and convert them into Mat floats for openCV processing. I'm using the Android NDK by the way, and this is the C++ part of the code.

My code below works fine on the Android emulator, but it stops when it gets to the float conversions when testing on my device (marked below), which leads me to think that it's a memory issue.

I'm new to managing memory with Android so I'd like to know how I'd go about fixing this issue.

//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;
SoronelHaetir
2#
SoronelHaetir Reply to 2018-01-11 22:14:30Z

About the only thing you can do in this situation is deal with the operations in series, that is to completely load training set 1, deal with it and then release the source data, then do the same for the remaining data. If memory is actually tight enough that you can't keep the data in memory at the same time well you need to make it so you don't try and do that.

Also note that the objects created by the AAssetManager_open calls are leaked.

You could do it in series with something like *not tested at all):

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);
}
You need to login account before you can post.

About| Privacy statement| Terms of Service| Advertising| Contact us| Help| Sitemap|
Processed in 0.298431 second(s) , Gzip On .

© 2016 Powered by mzan.com design MATCHINFO