一、前情提要以及工作目標
工作目標:做一個顯示單通道圖像的相機,實現(xiàn)預覽和拍照。
原本是調用opencv-android里邊的JavaCamera2View來實現(xiàn),這個用起來比較方便,它提供了集成好的相機預覽界面,并且提供了幀處理函數(shù)。但是問題是用opencv相機獲取到的幀圖片分辨率不高,達不到目標效果。
而CameraX作為Google發(fā)行的相機處理庫,可以方便的做分辨率設置、對焦等操作,于是決定使用Camerax+opencv的方式完成工作目標。
二、CameraX基礎
CameraX
Camerax(Android developer)
Camerax發(fā)布會(谷歌中國)
Camerax入門指南
三、工作幾大難點以及解決方案
(1). 開發(fā)語言與版本
CameraX主流語言是Kotlin, 網上帖子用的也大多是Kotlin,而我使用的是Java
并且Camerax目前為止發(fā)行了不少的版本,還分了alpha,beta版本,不同的版本代碼頁不完全兼容。Java開發(fā)盡可能選擇比較新的版本
Android CameraX 1.1.0 Java版本使用教程(Java)
(2). ImageProxy對象轉Mat
CameraX將相機應用的主流場景分成三個“用例”,每個用例都可以單獨使用:預覽
:將相機捕獲的畫面顯示在屏幕上,PreviewView拍照
:拍攝保存圖片分析ImageAnalysis
:提供每一幀圖像用于處理。
分析用例提供的是 ImageProxy對象,幀圖片是YUV類型,但是opencv處理的是Mat,所以需要進行轉換,可參考這篇文章:
YUV轉Mat
(3).圖片處理后的再顯示
我需要將每一幀處理后的圖像想普通相機那樣再顯示在界面上,但是CameraX的分析用例沒有提供返回,而且要將mat再轉回也比較麻煩,所以普遍的方式是在預覽界面的上面再疊放一個ImageView,每處理一幀就用ImageView顯示出來。(根據我的目標,我只要顯示處理之后的幀,所以我干脆沒有使用預覽用例)。
這里還要注意顯示的大小。我的ImageAnalysis分辨率設置的是1280x720, 顯示出來是不能占滿屏幕的,那么就有兩種處理方式:
1.使用ImageView的縮放設置setScaleType
ScaleType縮放設置
2.使用opencv的resize()函數(shù)
CameraX的預覽用例官方文檔中給出了預覽時的縮放規(guī)則,我仿照這個規(guī)則使用resize函數(shù)將負片進行縮放,并且ImageView縮放類型設置為Center
CameraX預覽用例文章來源:http://www.zghlxwxcb.cn/news/detail-811415.html
private class MyAnalyzer implements ImageAnalysis.Analyzer {
@SuppressLint("UnsafeOptInUsageError")
@Override
public void analyze(@NonNull ImageProxy image) {
Log.d(TAG, "Image's stamp is " + Objects.requireNonNull(image.getImage()).getTimestamp());
Image img = image.getImage();
int rotation = image.getImageInfo().getRotationDegrees();
//在opencv的JavaCamera2View.java中添加了ImageUtil類,用于YUV類型到mat的圖片轉換
ImageUtil imgutil = new ImageUtil(img);
Mat rgb = imgutil.rgba();
imgutil.rotation(rotation, rgb); //圖片旋轉
mChannelB = new Mat(rgb.height(), rgb.width(), CvType.CV_8UC1);
//clahe 用于進行圖像邊緣增強對比度
CLAHE clahe = createCLAHE();
clahe.setClipLimit(8);
clahe.setTilesGridSize(new Size(8, 8));
//通道拆分,僅顯示單通道圖像
List<Mat> imgList = new ArrayList<Mat>();
Core.split(rgb, imgList);
clahe.apply(imgList.get(2), mChannelB);
//獲取屏幕尺寸
DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
int width = displayMetrics.widthPixels;
int height = displayMetrics.heightPixels;
double mu=Math.max(mlay.getWidth()*1.0/mChannelB.width(),mlay.getHeight()*1.0/mChannelB.height());
Mat reRgb=new Mat();
resize(mChannelB,reRgb,new Size(0,0),mu,mu,INTER_CUBIC);
Bitmap bitmap = Bitmap.createBitmap(reRgb.width(), reRgb.height(), Bitmap.Config.ARGB_8888);
Utils.matToBitmap(reRgb,bitmap);
//TODO 處理我們要對Mat做的業(yè)務計算
imgutil.release(); //要釋放資源哦
// Toast.makeText(MainActivity.this,"mChannelB size:"+mChannelB.width()+";"+mChannelB.height(),Toast.LENGTH_SHORT).show();
/* String path= Environment.getExternalStorageDirectory()+"/DCIM/Camera/";
//將拍攝準確時間作為文件名
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss");
String filename = sdf.format(new Date());
String filePath= path + filename + ".jpg";
Imgcodecs.imwrite(filePath, mChannelB);
*/
image.close();
runOnUiThread(new Runnable() {
@Override
public void run() {
m_imageView.setImageBitmap(bitmap);
String size=mlay.getWidth()+"/"+mlay.getHeight()+";"+bitmap.getWidth()+"/"+bitmap.getHeight()+";"+m_imageView.getWidth()+"/"+m_imageView.getHeight()+";"+reRgb.width()+"/"+reRgb.height()+";mu:"+mu;
m_textView.setText(size);
// Toast.makeText(MainActivity.this,"imageview size:"+m_imageView.getWidth()+";"+m_imageView.getHeight(),Toast.LENGTH_SHORT).show();
}
});
}
}
文章來源地址http://www.zghlxwxcb.cn/news/detail-811415.html
到了這里,關于Android Studio開發(fā)之路(七)CameraX&&Opencv的使用的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網!