Android OpenCV 应用程序的内存问题

Memory issue with Android OpenCV application

本文关键字:内存 问题 应用程序 OpenCV Android      更新时间:2023-10-16

我想加载 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,处理它然后释放源数据,然后对剩余数据执行相同的操作。如果内存实际上足够紧,以至于您无法同时将数据保存在内存中,则需要这样做,这样您就不会尝试这样做。

另请注意,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);
}