OpenCVにてCameraのInput Size変更してViewにOutputする時 BitmapErrerが出るときに対処(Android)

AndroidOpenCVにてCameraのInputをTextureViewに出力する時

MatのRotationやResizeを行い、return Mat;をするとBitmap系のErrerが出ます。

用途:カメラの向きが90度傾いているのを戻したい、高速化のためshrinkにしたMatをEnlargeしたくない。

 

エラーが起きている場所は、"CameraBridgeViewBase.java"の、MatをBitmapに変換する処理の様です。

 

以下のメソッドに

protected void deliverAndDrawFrame(CvCameraViewFrame frame) {

Mat modified;

if (mListener != null) {
modified = mListener.onCameraFrame(frame);

 

ReturnしたMatをBitmapに引き渡す処理がありますが、(その先は未解析)

BitmapSizeはCameraのPreviewSizeで初期化された後、Mat Size合わせて変更する処理が無いため、Cameraと違うMat SizeをmCacheBitmap入れると怒られてしまします。

Utils.matToBitmap(modified, mCacheBitmap);

 

ですので、以下の様にメソッドに追加します。(自己流:modifiedのサイズでBitmapを再生成:mScale値は不要です。)

 

(追加箇所://add :mat AutoFIt :Start と //add :mat AutoFIt :End の間の処理)

/**
* This method shall be called by the subclasses when they have valid
* object and want it to be delivered to external client (via callback) and
* then displayed on the screen.
* @param frame - the current frame to be delivered
*/
protected void deliverAndDrawFrame(CvCameraViewFrame frame) {
Mat modified;

if (mListener != null) {
modified = mListener.onCameraFrame(frame);
} else {
modified = frame.rgba();
}

boolean bmpValid = true;
if (modified != null) {
try {
//add :mat AutoFIt :Start
if(modified.cols() != mCacheBitmap.getWidth() || modified.rows() != mCacheBitmap.getHeight()){
Log.d(TAG, " mCacheBitmap.getWidth():" +mCacheBitmap.getWidth() +" mCacheBitmap.getHeight():" +mCacheBitmap.getHeight());
mCacheBitmap = Bitmap.createBitmap(modified.cols(), modified.rows(), Bitmap.Config.ARGB_8888);
float scaleHeight = (float) mFrameHeight/ (float) modified.rows() ;
float scaleWidth = (float) mFrameWidth / (float) modified.cols();
mScale = scaleWidth > scaleHeight ? scaleWidth: scaleHeight;
Log.d(TAG, " mScale:" +mScale +" scaleWidth:" +scaleWidth
+" scaleHeight:" +scaleHeight
+" mMaxWidth:" +mMaxWidth +" mMaxHeight:" +mMaxHeight
+" mFrameWidth:" +mFrameWidth +" mFrameHeight:" +mFrameHeight
+" modified.cols():" +modified.cols() +" modified.rows():" +modified.rows());
}
//add :mat AutoFIt :End
Utils.matToBitmap(modified, mCacheBitmap);
} catch(Exception e) {
Log.e(TAG, "Mat type: " + modified);
Log.e(TAG, "Bitmap type: " + mCacheBitmap.getWidth() + "*" + mCacheBitmap.getHeight());
Log.e(TAG, "Utils.matToBitmap() throws an exception: " + e.getMessage());
bmpValid = false;
}
}

if (bmpValid && mCacheBitmap != null) {
Canvas canvas = getHolder().lockCanvas();
if (canvas != null) {
canvas.drawColor(0, android.graphics.PorterDuff.Mode.CLEAR);
if (BuildConfig.DEBUG)
Log.d(TAG, "mStretch value: " + mScale);

if (mScale != 0) {
canvas.drawBitmap(mCacheBitmap, new Rect(0,0,mCacheBitmap.getWidth(), mCacheBitmap.getHeight()),
new Rect*1 / 2),
(int)*2 / 2),
(int)*3 / 2 + mScale*mCacheBitmap.getWidth()),
(int)*4 / 2 + mScale*mCacheBitmap.getHeight())), null);
} else {
canvas.drawBitmap(mCacheBitmap, new Rect(0,0,mCacheBitmap.getWidth(), mCacheBitmap.getHeight()),
new Rect*5 / 2,
(canvas.getHeight() - mCacheBitmap.getHeight()) / 2,
(canvas.getWidth() - mCacheBitmap.getWidth()) / 2 + mCacheBitmap.getWidth(),
(canvas.getHeight() - mCacheBitmap.getHeight()) / 2 + mCacheBitmap.getHeight()), null);
}

if (mFpsMeter != null) {
mFpsMeter.measure();
mFpsMeter.draw(canvas, 20, 30);
}
getHolder().unlockCanvasAndPost(canvas);
}
}
}

 

 

 

*1:int)((canvas.getWidth() - mScale*mCacheBitmap.getWidth(

*2:canvas.getHeight() - mScale*mCacheBitmap.getHeight(

*3:canvas.getWidth() - mScale*mCacheBitmap.getWidth(

*4:canvas.getHeight() - mScale*mCacheBitmap.getHeight(

*5:canvas.getWidth() - mCacheBitmap.getWidth(