編輯:關於android開發
在上篇中我們已經實現了相機打開和實時圖像信息的獲取,那麼接下來我們可以嘗試在獲取的圖像信息進行一些處理,然後實時顯示出來,在這裡我們要完成的的幾種處理:
灰化、Canny邊緣檢測、Hist直方圖計算、Sobel邊緣檢測、SEPIA(色調變換)、ZOOM放大鏡、PIXELIZE像素化
一、修改布局界面:
由於這裡我們需要切換不同的圖像處理模式,所以這裡我們需要在界面上放置一個按鈕,我們可以放置很多個按鈕,每個按鈕對應一種處理模式,但是這裡我們也可以只放置一個按鈕,每次點擊按鈕就切換一次,循環切換模式:
activity_main.xml文件:
<framelayout android:layout_height="match_parent" android:layout_width="match_parent" xmlns:android="http://schemas.android.com/apk/res/android" xmlns:opencv="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools">查看預覽圖:</framelayout>
二、獲取按鈕組件並監聽按鈕點擊:
1.聲明一個Button對象用於綁定上面的按鈕組件和一個狀態標志位用於存儲當前狀態:
//按鈕組件 private Button mButton; //當前處理狀態 private static int Cur_State = 0;
2.在OnCreate中綁定按鈕和按鈕點擊監聽:
mButton = (Button) findViewById(R.id.deal_btn); mButton.setOnClickListener(new OnClickListener(){ @Override public void onClick(View v) { if(Cur_State<8){ //切換狀態 Cur_State ++; }else{ //恢復初始狀態 Cur_State = 0; } } });這裡的狀態標志位Cur_State與圖像處理的每個類型對應,0對應默認狀態,也就是顯示原圖,1-7分別對應:灰化、Canny邊緣檢測、Hist直方圖計算、Sobel邊緣檢測、SEPIA(色調變換)、ZOOM放大鏡、PIXELIZE像素化
1.在OpenCV中一般都是使用Mat類型來存儲圖像等矩陣信息,所以我們可以聲明一個Mat對象用來作為實時幀圖像的緩存對象:
//緩存相機每幀輸入的數據 private Mat mRgba;
2.對象實例化以及基本屬性的設置,包括:長度、寬度和圖像類型標志:
public void onCameraViewStarted(int width, int height) { // TODO Auto-generated method stub mRgba = new Mat(height, width, CvType.CV_8UC4); }
3.對象賦值,這裡只對原圖和灰化兩種情況進行了處理,其他的處理後續再添加:
/** * 圖像處理都寫在此處 */ @Override public Mat onCameraFrame(CvCameraViewFrame inputFrame) { switch (Cur_State) { case 1: //灰化處理 Imgproc.cvtColor(inputFrame.gray(), mRgba, Imgproc.COLOR_GRAY2RGBA,4); break; default: //顯示原圖 mRgba = inputFrame.rgba(); break; } //返回處理後的結果數據 return mRgba; }
4.由於用對象存儲圖像數據的話,數據會保存到內存中,所以結束的時候需要進行數據釋放,不然可能導致崩潰:
@Override public void onCameraViewStopped() { // TODO Auto-generated method stub mRgba.release(); }
正常模式:
灰化圖:
四、其他處理及結果:
在以上的例子中我們已經完成了預覽圖的灰化處理,那麼接下來我們把其他處理都添加到代碼中,查看效果。由於在2.x版本中使用到的部分方法已經發生了變化,如:在OpenCV 3.1.0中org.opencv.core.Core類中的方法line和rectangle都已失效,可以用org.opencv.imgproc.Imgproc中的line和rectangle來代替:
1. MainActivity.java源碼:
package com.linsh.opencv_test; import java.util.Arrays; import org.opencv.android.BaseLoaderCallback; import org.opencv.android.CameraBridgeViewBase; import org.opencv.android.OpenCVLoader; import org.opencv.android.CameraBridgeViewBase.CvCameraViewFrame; import org.opencv.android.CameraBridgeViewBase.CvCameraViewListener2; import org.opencv.android.LoaderCallbackInterface; import org.opencv.core.Core; import org.opencv.core.CvType; import org.opencv.core.Mat; import org.opencv.core.MatOfFloat; import org.opencv.core.MatOfInt; import org.opencv.core.Point; import org.opencv.core.Scalar; import org.opencv.core.Size; import org.opencv.imgproc.Imgproc; import android.R.string; import android.app.Activity; import android.os.Bundle; import android.util.Log; import android.widget.Button; import android.view.View; import android.view.View.OnClickListener; public class MainActivity extends Activity implements CvCameraViewListener2{ private String TAG = "OpenCV_Test"; //OpenCV的相機接口 private CameraBridgeViewBase mCVCamera; //緩存相機每幀輸入的數據 private Mat mRgba,mTmp; //按鈕組件 private Button mButton; //當前處理狀態 private static int Cur_State = 0; private Size mSize0; private Mat mIntermediateMat; private MatOfInt mChannels[]; private MatOfInt mHistSize; private int mHistSizeNum = 25; private Mat mMat0; private float[] mBuff; private MatOfFloat mRanges; private Point mP1; private Point mP2; private Scalar mColorsRGB[]; private Scalar mColorsHue[]; private Scalar mWhilte; private Mat mSepiaKernel; /** * 通過OpenCV管理Android服務,異步初始化OpenCV */ BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) { @Override public void onManagerConnected(int status){ switch (status) { case LoaderCallbackInterface.SUCCESS: Log.i(TAG,"OpenCV loaded successfully"); mCVCamera.enableView(); break; default: break; } } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mCVCamera = (CameraBridgeViewBase) findViewById(R.id.camera_view); mCVCamera.setCvCameraViewListener(this); mButton = (Button) findViewById(R.id.deal_btn); mButton.setOnClickListener(new OnClickListener(){ @Override public void onClick(View v) { if(Cur_State<8){ //切換狀態 Cur_State ++; }else{ //恢復初始狀態 Cur_State = 0; } } }); } @Override public void onResume() { super.onResume(); if (!OpenCVLoader.initDebug()) { Log.d(TAG,"OpenCV library not found!"); } else { Log.d(TAG, "OpenCV library found inside package. Using it!"); mLoaderCallback.onManagerConnected(LoaderCallbackInterface.SUCCESS); } }; @Override public void onDestroy() { if(mCVCamera!=null){ mCVCamera.disableView(); } }; @Override public void onCameraViewStarted(int width, int height) { // TODO Auto-generated method stub mRgba = new Mat(height, width, CvType.CV_8UC4); mTmp = new Mat(height, width, CvType.CV_8UC4); mIntermediateMat = new Mat(); mSize0 = new Size(); mChannels = new MatOfInt[] { new MatOfInt(0), new MatOfInt(1), new MatOfInt(2) }; mBuff = new float[mHistSizeNum]; mHistSize = new MatOfInt(mHistSizeNum); mRanges = new MatOfFloat(0f, 256f); mMat0 = new Mat(); mColorsRGB = new Scalar[] { new Scalar(200, 0, 0, 255), new Scalar(0, 200, 0, 255), new Scalar(0, 0, 200, 255) }; mColorsHue = new Scalar[] { new Scalar(255, 0, 0, 255), new Scalar(255, 60, 0, 255), new Scalar(255, 120, 0, 255), new Scalar(255, 180, 0, 255), new Scalar(255, 240, 0, 255), new Scalar(215, 213, 0, 255), new Scalar(150, 255, 0, 255), new Scalar(85, 255, 0, 255), new Scalar(20, 255, 0, 255), new Scalar(0, 255, 30, 255), new Scalar(0, 255, 85, 255), new Scalar(0, 255, 150, 255), new Scalar(0, 255, 215, 255), new Scalar(0, 234, 255, 255), new Scalar(0, 170, 255, 255), new Scalar(0, 120, 255, 255), new Scalar(0, 60, 255, 255), new Scalar(0, 0, 255, 255), new Scalar(64, 0, 255, 255), new Scalar(120, 0, 255, 255), new Scalar(180, 0, 255, 255), new Scalar(255, 0, 255, 255), new Scalar(255, 0, 215, 255), new Scalar(255, 0, 85, 255), new Scalar(255, 0, 0, 255) }; mWhilte = Scalar.all(255); mP1 = new Point(); mP2 = new Point(); // Fill sepia kernel mSepiaKernel = new Mat(4, 4, CvType.CV_32F); mSepiaKernel.put(0, 0, /* R */0.189f, 0.769f, 0.393f, 0f); mSepiaKernel.put(1, 0, /* G */0.168f, 0.686f, 0.349f, 0f); mSepiaKernel.put(2, 0, /* B */0.131f, 0.534f, 0.272f, 0f); mSepiaKernel.put(3, 0, /* A */0.000f, 0.000f, 0.000f, 1f); } @Override public void onCameraViewStopped() { // TODO Auto-generated method stub mRgba.release(); mTmp.release(); } /** * 圖像處理都寫在此處 */ @Override public Mat onCameraFrame(CvCameraViewFrame inputFrame) { mRgba = inputFrame.rgba(); Size sizeRgba = mRgba.size(); int rows = (int) sizeRgba.height; int cols = (int) sizeRgba.width; Mat rgbaInnerWindow; int left = cols / 8; int top = rows / 8; int width = cols * 3 / 4; int height = rows * 3 / 4; switch (Cur_State) { case 1: //灰化處理 Imgproc.cvtColor(inputFrame.gray(), mRgba, Imgproc.COLOR_GRAY2RGBA,4); break; case 2: //Canny邊緣檢測 mRgba = inputFrame.rgba(); Imgproc.Canny(inputFrame.gray(), mTmp, 80, 100); Imgproc.cvtColor(mTmp, mRgba, Imgproc.COLOR_GRAY2RGBA, 4); break; case 3: //Hist直方圖計算 Mat hist = new Mat(); int thikness = (int) (sizeRgba.width / (mHistSizeNum + 10) / 5); if(thikness > 5) thikness = 5; int offset = (int) ((sizeRgba.width - (5*mHistSizeNum + 4*10)*thikness)/2); // RGB for(int c=0; c<3; c++) { Imgproc.calcHist(Arrays.asList(mRgba), mChannels[c], mMat0, hist, mHistSize, mRanges); Core.normalize(hist, hist, sizeRgba.height/2, 0, Core.NORM_INF); hist.get(0, 0, mBuff); for(int h=0; h
2.效果圖:
Canny邊緣檢測:
Hist直方圖計算:
Sobel邊緣檢測:
SEPIA(色調變換):
ZOOM放大鏡:
PIXELIZE像素化:
BLE-NRF51822教程3-sdk程序框架剖析nordicBLE 技術交流群498676838本講為框架介紹,不會牽涉到太多代碼細節。 51822的官方SDK其實是
android自定義控件實現刮刮樂效果,android刮刮樂 只是簡單的實現了效果,界面沒怎麼做優化,不過那都是次要的啦!! 其中主要的彩票視圖類和橡皮擦類都是通過代碼
將語音搜索集成到Google Now中,googlenow原文標題:Use Voice Search to integrate with Google Now 原文鏈接:
Android編程之客戶端通過socket與服務器通信的方法 Android編程之客戶端通過socket與服務器通信的方法 &n
ErrorExecution failed for task '