您好,登錄后才能下訂單哦!
OpenCV4Android中如何運用手機攝像頭獲取Canny邊緣,相信很多沒有經驗的人對此束手無策,為此本文總結了問題出現的原因和解決方法,通過這篇文章希望你能解決這個問題。
在圖像中獲取主要影響的邊緣用處比較廣泛,這樣就用到了Canny邊緣的效果
Canny邊緣的提取流程
高斯模糊
梯度計算
非最大信息壓制
高低閾值鏈接
顯示
還是用我們的Demo
不過這次我們加上新的東西,因為正好學習了OpenCV里面調用手機里的攝像頭功能獲取圖片信息,花了整整一天算是入了個門吧.
首先在原來的MainActivity里面增加一個按鈕
對應增加的事件
照相機頁面
首先我們增加了一個opencvcarema.xml頁面和一個OpenCVCarema的activity
opencvcarema.xml
這里面可以直接增加org.opencv.android.JavaCameraView,然后又在下方增加了一個按鈕
OpenCvCarema
這個class我們需要繼承Activity并且引用了
CameraBridgeViewBase.CvCameraViewListener2
里面幾個的方法
按鈕獲取當前圖像提取邊緣
里面就是根據獲取的圖像創建一個bitbmp的圖像,然后把獲取的圖像mRgbaF先用高斯模糊后,再轉成灰度圖,然后再運用Canny邊緣提取出新的Mat,再將提取完的轉回為bmp圖像,因為我們需要返回數據,所以返回時把bmp圖像轉為byte[]發送回去,原來我們的MainActivity里的onActivityResult里面增加了返回照相機數據
照相機獲取圖像時加入了橫豎屏的判斷
在OpenCV調用照相機時,默認的都是橫屏,所以我們豎屏手機打開時會是個90的旋轉樣子,非常不友好,經常查找資料和多次測試,我自己修改了onCameraFrame這個函數
標紅的這塊是就是判斷當前手機屏幕是橫屏和豎屏,通過寬度和高度進行對比,寬度大于高度時就是橫屏,小于時就是豎屏.
如果是豎屏我們就執行以下步驟:
先將水平圖像轉為垂直.
轉完后的圖像再縮放為原來的大小.
再將圖像沿Y軸進行翻轉(如果不翻轉的話看到的圖像是左右互調的)
下面的我們的視頻效果,最后有OpenCVCarema.java整個類的代碼
下面的整個OpenCvCarema.java的類
package dem.vaccae.opencvdemo;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Camera;
import android.os.Bundle;
import android.os.PersistableBundle;
import android.support.annotation.Nullable;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import org.opencv.android.CameraBridgeViewBase;
import org.opencv.android.OpenCVLoader;
import org.opencv.android.Utils;
import org.opencv.core.Core;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.core.Size;
import org.opencv.imgproc.Imgproc;
import java.io.ByteArrayOutputStream;
/**
* Created by Administrator on 2018-01-01.
*/
public class OpenCvCarema extends Activity implements CameraBridgeViewBase.CvCameraViewListener2 {
private static final String TAG = "OpenCvCameraActivity";
static {
OpenCVLoader.initDebug();
}
private Mat mRgba;
private Mat mRgbaF;
private Mat mFlipRgba;
private Camera mCamera;
private CameraBridgeViewBase mOpenCvCameraView;
private Button btnCanny;
//是否按下按鍵
private boolean isbtn = false;
private Bitmap bmp;
public OpenCvCarema() {
Log.i(TAG, "Instantiated new " + this.getClass());
}
@Override
public void onCreate(Bundle savedInstanceState) {
Log.i(TAG, "called onCreate");
super.onCreate(savedInstanceState);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
setContentView(R.layout.opencvcarema);
mOpenCvCameraView = findViewById(R.id.opencvcaremaview);
mOpenCvCameraView.enableView();
mOpenCvCameraView.setCvCameraViewListener(this);
//后置攝像頭
mOpenCvCameraView.setCameraIndex(CameraBridgeViewBase.CAMERA_ID_BACK);
btnCanny = findViewById(R.id.btnCanny);
btnCanny.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
isbtn = true;
bmp = Bitmap.createBitmap(mRgbaF.width(), mRgbaF.height(), Bitmap.Config.ARGB_8888);
//先進行高斯模糊
Imgproc.GaussianBlur(mRgbaF, mRgbaF, new Size(3, 3), 0, 0, Imgproc.BORDER_DEFAULT);
//先改為灰度圖像
Imgproc.cvtColor(mRgbaF, mRgbaF, Imgproc.COLOR_BGRA2GRAY);
//t代表低閾值,高閾值一般是低閾值的2倍,所以threshold用t*2或t*3即可,
//apertureSize這里輸入3,就是代表3*3的眼膜
//L2gradient這個是對精度要求,如果是true精度會高,但是會慢,所以一般來說我們都用false就可以了
Imgproc.Canny(mRgbaF, mFlipRgba, 112, 112 * 2, 3, false);
Utils.matToBitmap(mFlipRgba, bmp);
//將圖片壓縮成byte[]傳遞回去
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bmp.compress(Bitmap.CompressFormat.PNG, 100, baos);
byte[] bitmapByte = baos.toByteArray();
Intent rtnintent = new Intent();
rtnintent.putExtra("bitmap", bitmapByte);
OpenCvCarema.this.setResult(Activity.RESULT_OK, rtnintent);
finish();
}
});
}
@Override
protected void onPause() {
super.onPause();
if (mOpenCvCameraView != null)
mOpenCvCameraView.disableView();
}
@Override
protected void onResume() {
super.onResume();
}
@Override
protected void onDestroy() {
super.onDestroy();
mOpenCvCameraView.disableView();
}
@Override
public void onCameraViewStarted(int width, int height) {
mRgba = new Mat();
mRgbaF = new Mat();
mFlipRgba = new Mat();
}
@Override
public void onCameraViewStopped() {
mFlipRgba.release();
mRgbaF.release();
}
@Override
public Mat onCameraFrame(CameraBridgeViewBase.CvCameraViewFrame inputFrame) {
if (!isbtn) {
//注意
mRgba = inputFrame.rgba();
//獲取屏幕寬和高用于判斷是橫屏還是豎屏
DisplayMetrics dm = getResources().getDisplayMetrics();
if (dm.widthPixels < dm.heightPixels) {
//轉置函數,可以水平的圖像變為垂直
Core.transpose(mRgba, mFlipRgba);
//將轉置后的圖像縮放為mRgbaF的大小
Imgproc.resize(mFlipRgba, mRgbaF, mRgba.size(), 0.0D, 0.0D, 0);
//flipCode>0將mRgbaF水平翻轉(沿Y軸翻轉)得到mRgba
Core.flip(mRgbaF, mRgbaF, 1);
} else {
mRgbaF = mRgba;
}
}
return mRgbaF;
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
return true;
}
}
看完上述內容,你們掌握OpenCV4Android中如何運用手機攝像頭獲取Canny邊緣的方法了嗎?如果還想學到更多技能或想了解更多相關內容,歡迎關注億速云行業資訊頻道,感謝各位的閱讀!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。