Android と IOS で動作するモバイル アプリケーションを開発しています。ビデオストリームのリアルタイム処理が可能です。Android では、android.hardware.Camera.PreviewCallback.onPreviewFrame 経由でカメラの Preview-Videostream を取得します。NV21-Format はすべての Android デバイスでサポートされているはずですが、RGB はサポートされていません (または RGB565 のみ)。
主にパターン認識用の私のアルゴリズムでは、グレースケール画像と色情報が必要です。グレースケールは問題ありませんが、NV21 から BGR への色変換に時間がかかりすぎます。
説明したように、次の方法を使用して画像をキャプチャします。
アプリでは、カメラの onPreviewFrame-Handler をオーバーライドします。これは CameraPreviewFrameHandler.java で行われます。
@Override
public void onPreviewFrame(byte[] data, Camera camera) {
{
try {
AvCore.getInstance().onFrame(data, _prevWidth, _prevHeight, AvStreamEncoding.NV21);
} catch (NativeException e)
{
e.printStackTrace();
}
}
次に、onFrame-Function はネイティブ関数を呼び出します。この関数は、Java オブジェクトからデータをローカル参照としてフェッチします。次に、これは unsigned char* バイトストリームに変換され、OpenCV を使用して NV21 から BGR に変換する次の c++ 関数を呼び出します。
void CoreManager::api_onFrame(unsigned char* rImageData, avStreamEncoding_t vImageFormat, int vWidth, int vHeight)
{
// rImageData is a local JNI-reference to the java-byte-array "data" from onPreviewFrame
Mat bgrMat; // Holds the converted image
Mat origImg; // Holds the original image (OpenCV-Wrapping around rImageData)
double ts; // for profiling
switch(vImageFormat)
{
// other formats
case NV21:
origImg = Mat(vHeight + vHeight/2, vWidth, CV_8UC1, rImageData); // fast, only creates header around rImageData
bgrMat = Mat(vHeight, vWidth, CV_8UC3); // Prepare Mat for target image
ts = avUtils::gettime(); // PROFILING START
cvtColor(origImg, bgrMat, CV_YUV2BGRA_NV21);
_onFrameBGRConversion.push_back(avUtils::gettime()-ts); // PROFILING END
break;
}
[...APPLICATION LOGIC...]
}
コード内のコメントから結論付けられるように、私はすでに変換をプロファイリングしましたが、Nexus 4 で約 30 ミリ秒かかることが判明しました。(私のプロファイリング方法は再確認され、リアルタイム測定のために適切に機能しています)
現在、NV21 から BGR へのこの色変換のより高速な実装を必死に見つけようとしています。これは私がすでに行ったことです。
- このトピックで提供されているコード「convertYUV420_NV21toRGB8888」を C++ に採用(変換時間の倍数)
- 整数演算のみを使用するようにコードを 1 から変更しました (openCV-Solution の 2 倍の変換時間)
- 他のいくつかの実装を参照しましたが、すべて同様の変換時間でした
- OpenCV-Implementation を確認すると、パフォーマンスを得るために多くのビットシフトが使用されます。自力では上手くいかないと思います
提案がありますか、良い実装を知っていますか、またはこの問題を回避するためのまったく異なる方法がありますか? どうにかして Android カメラから RGB/BGR フレームをキャプチャする必要があり、できるだけ多くの Android デバイスで動作するはずです。
返信ありがとうございます。