В демонстрационном Android-коде tenorflow-lite для классификации изображений изображения сначала преобразуются в формат ByteBuffer для повышения производительности. Это преобразование из растрового формата в формат с плавающей запятой и последующее преобразование в байтовый буфер представляется дорогостоящей операцией (циклы, побитовые операторы, float mem-copy и т. д.) Мы пытались реализовать ту же логику с opencv, чтобы получить некоторое преимущество в скорости. Следующий код работает без ошибок; но из-за некоторой логической ошибки в этом преобразовании выходные данные модели (в которую эти данные передаются) кажутся неверными. Предполагается, что входные данные модели будут RGB с типом данных float [1 197 197,3].
Как мы можем ускорить этот процесс преобразования растрового изображения в байтовый буфер, используя opencv (или любым другим способом)?
Преобразование стандартного растрового изображения в байтовый буфер: -
/** Writes Image data into a {@code ByteBuffer}. */
private void convertBitmapToByteBuffer(Bitmap bitmap) {
if (imgData == null) {
return;
}
imgData.rewind();
bitmap.getPixels(intValues, 0, bitmap.getWidth(), 0, 0, bitmap.getWidth(), bitmap.getHeight());
long startTime = SystemClock.uptimeMillis();
// Convert the image to floating point.
int pixel = 0;
for (int i = 0; i < getImageSizeX(); ++i) {
for (int j = 0; j < getImageSizeY(); ++j) {
final int val = intValues[pixel++];
imgData.putFloat(((val>> 16) & 0xFF) / 255.f);
imgData.putFloat(((val>> 8) & 0xFF) / 255.f);
imgData.putFloat((val & 0xFF) / 255.f);
}
}
long endTime = SystemClock.uptimeMillis();
Log.d(TAG, "Timecost to put values into ByteBuffer: " + Long.toString(endTime - startTime));
}
Битовая карта OpenCV в ByteBuffer: -
/** Writes Image data into a {@code ByteBuffer}. */
private void convertBitmapToByteBuffer(Bitmap bitmap) {
if (imgData == null) {
return;
}
imgData.rewind();
bitmap.getPixels(intValues, 0, bitmap.getWidth(), 0, 0, bitmap.getWidth(), bitmap.getHeight());
long startTime = SystemClock.uptimeMillis();
Mat bufmat = new Mat(197,197,CV_8UC3);
Mat newmat = new Mat(197,197,CV_32FC3);
Utils.bitmapToMat(bitmap,bufmat);
Imgproc.cvtColor(bufmat,bufmat,Imgproc.COLOR_RGBA2RGB);
List<Mat> sp_im = new ArrayList<Mat>(3);
Core.split(bufmat,sp_im);
sp_im.get(0).convertTo(sp_im.get(0),CV_32F,1.0/255/0);
sp_im.get(1).convertTo(sp_im.get(1),CV_32F,1.0/255.0);
sp_im.get(2).convertTo(sp_im.get(2),CV_32F,1.0/255.0);
Core.merge(sp_im,newmat);
//bufmat.convertTo(newmat,CV_32FC3,1.0/255.0);
float buf[] = new float[197*197*3];
newmat.get(0,0,buf);
//imgData.wrap(buf).order(ByteOrder.nativeOrder()).getFloat();
imgData.order(ByteOrder.nativeOrder()).asFloatBuffer().put(buf);
long endTime = SystemClock.uptimeMillis();
Log.d(TAG, "Timecost to put values into ByteBuffer: " + Long.toString(endTime - startTime));
}