在tensorflow-lite的Android图像分类演示代码中,为了提高性能,首先将图像转换为ByteBuffer格式。从位图到浮点格式的转换以及随后的转换为字节缓冲区似乎是一项昂贵的操作(循环、位运算符、浮点存储器复制等)。我们尝试使用opencv实现相同的逻辑,以获得一些速度优势。以下代码可以正常工作,但由于此转换中存在某些逻辑错误,因此向模型输入数据的输出似乎不正确。模型的输入应该是RGB格式,数据类型为float[1,197,197,3]。
如何使用opencv (或其他任何方法)加快位图到字节缓冲区转换过程的速度?
标准位图到ByteBuffer转换:
如何使用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();
// 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));
}