當前位置:首頁 » 安卓系統 » androidopencv教程

androidopencv教程

發布時間: 2024-09-22 15:04:59

『壹』 濡備綍鍦╩ac緋葷粺涓婁嬌鐢╫pencv for android

銆銆mac緋葷粺鍦╬ython涓婂畨瑁呴厤緗畂pencv鐨勬ラわ細 銆銆1 涓嬭澆鏈鏂扮増OpenCV for Linux/Mac婧愭枃浠訛紝鐩鍓嶇増鏈鏄2.4.3銆備笅杞藉悗瑙e帇銆 銆銆2. 鍘 涓嬭澆鏈鏂扮増cmake錛.dmg鏂囦歡錛岀洰鍓嶇増鏈鏄2.8.10.2銆備笅杞藉悗瀹夎呫 銆銆3. 鎺ヤ笅鏉ュ紑濮嬪畨瑁卭pencv 銆銆寮涓涓緇堢錛岃繘鍏opencv瑙e帇緙╃殑鐩褰曪紝濡俢d 鐒跺悗鎶婃枃浠跺す鎷借繘鍘匯 銆銆mkdir release 銆銆cd ./release 銆銆cmake -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_INSTALL_PREFIX=/usr/local -D BUILD_PYTHON_SUPPORT=ON -D BUILD_EXAMPLES=ON .. 銆銆make 銆銆sudo make install 銆銆4. 鑷蟲opencv宸茬粡瑁呬笂浜嗐

『貳』 Android OpenCV(二十三):Sobel運算元邊緣檢測

Sobel運算元在計算機視覺中扮演著邊緣檢測的重要角色。它通過加權計算圖像中每個像素周圍上下左右的灰度值差異,尤其在邊緣區域,其結果會達到峰值,從而有效地識別邊緣。索貝爾運算元本質上是一種離散差分運算元,用於估算亮度函數的梯度近似值,給出每個像素的梯度矢量或其法矢量。這個運算元不僅效果顯著,還能在一定程度上平滑雜訊,但可能產生較為粗糙的邊緣,且有時會出現偽邊緣現象。

索貝爾運算元使用兩組3x3的矩陣,分別進行水平和垂直方向的濾波,其數學表達式為:若原始圖像為A,經處理後的橫向和縱向邊緣圖像分別記為Gx和Gy。計算每個像素的梯度大小和方向的公式如下:

當計算出的梯度方向θ為零時,意味著圖像中的邊緣是縱向的,即圖像的左側比右側暗。

在實際應用中,函數中的第三個、第四個和第五個參數對於邊緣檢測效果至關重要。這些參數的關系是,任何方向的差分階數都必須小於濾波器尺寸,特殊情況是當ksize=1時,需保證任意方向的階數小於3。一般而言,如果差分階數最大值為1,濾波器尺寸為3;最大值為2,濾波器尺寸為5;最大值為3,濾波器尺寸為7。當ksize為1時,濾波器會變為非正方形,如3x1或1x3。最後三個參數,通常情況下保持默認值,除非有特定需求。

『叄』 Android項目引入OpenCV和FFmpeg

在安卓項目中引入OpenCV和FFmpeg庫,本文以OpenCV-4.5.1和FFmpeg-4.4版本為例,詳述引入過程。引入庫需遵循以下步驟:

1. **新建Android C++工程**

2. **下載OpenCV-Android-SDK**

3. **導入OpenCV-SDK至Android工程**

4. **修改OpenCV庫的SDK版本**

5. **APP引入OpenCV依賴**

6. **復制庫文件至指定目錄**

7. **編輯CMakeList.txt**

8. **相關學習資源**

9. **初始化OpenCV**

引入庫後會面臨安裝包體積增大的問題,以及使用JNI時的C++學習需求。在引入庫過程中,遇到錯誤時應耐心查找資料,了解各版本間的編譯或使用差異。復制錯誤信息上網搜索解決方案,逐步解決問題,最終成功引入庫。

總結經驗:**耐心查找資料**,理解庫版本間的區別,遇到錯誤時直接查找解決方案,分步操作以確保成功。

引用資源:

1. **AndroidStudio使用OpenCV的三種方式**

2. **在macOS上使用 NDK20 編譯ffmpeg4.2.2的過程** 作者:koinzhang 鏈接:juejin.cn/post/69513309...

『肆』 如何在Android中使用OpenCV

如何在Android程序中使用OpenCV

有兩種方式(重點講後面一種):

1.使用OpenCV java API。

OpenCV安裝路徑"F:OpenCV-2.3.1-android-bin"下有兩個文件夾


將文件夾"OpenCV-2.3.1"拷貝到你的Eclipse工作空間所在的目錄,也就是在你的項目的上一級目錄中,然後導入到工作空間中,在Package Explorer中選擇你的項目,單機右鍵在彈出菜單中選擇Properties,然後在彈出的Properties窗口中左側選擇Android,然後點擊右下方的Add按鈕,選擇OpenCV-2.3.1並點擊OK,


此時,展開你的項目樹,你可以看到新加了一個OpenCV-2.3.1_src目錄,如下圖,那麼就是正確添加了OpenCV Java API,否則就是你放置OpenCV-2.3.1的目錄路徑不正確。


然後就可以在你的Java源文件中導入OpenCV的API包,並且使用OpenCV API了,OpenCV API的包的形式如下:

Org.opencv.(OpenCV模塊名).(OpenCV類名)

例如:

Org.opencv.core.Mat

2.利用JNI編寫C++ OpenCV代碼,通過Android NDK創建動態庫(.so)

新建一個工作空間,例如"TestOpenCV",在Window->Preferences中設置好Android SDK的路徑。


然後新建一個Android項目,Build Target選擇Android2.2,命名為"HaveImgFun",活動名改為HaveImgFun,Package name中填寫com.testopencv.haveimgfun,最後點擊finish。

如同使用OpenCV Java API那樣,將OpenCV-2.3.1文件夾拷貝到與工作空間同一級目錄中;另外,將"F:OpenCV-2.3.1-android-binsamples"下的includeOpenCV.mk文件拷貝到和項目HaveImgFun同一級目錄中:


(上面這個各個文件夾和文件的放置很重要,因為OpenCV-2.3.1下的OpenCV.mk中有很多相對路徑的指定,如果不是這樣放置,在NDK生成動態庫時可能會報文件或文件夾無法找到的錯誤)

選擇Package Explorer中你的項目,右鍵選擇new->folder,新建一個名為jni的文件夾,用來存放你的c/c++代碼。

然後把res->layout下的main.xml的內容改為下面所示:


1 <?xml version="1.0" encoding="utf-8"?>
2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
3 android:orientation="vertical"
4 android:layout_width="fill_parent"
5 android:layout_height="fill_parent"
6 >
7 <Button android:layout_height="wrap_content"
8 android:layout_width="fill_parent"
9 android:id="@+id/btnNDK"
10 android:text="使用C++ OpenCV進行處理" />
11 <Button android:layout_height="wrap_content"
12 android:layout_width="fill_parent"
13 android:id="@+id/btnRestore"
14 android:text="還原" />
15 <ImageView android:id="@+id/ImageView01"
16 android:layout_width="fill_parent"
17 android:layout_height="fill_parent" />
18 </LinearLayout>


上面的代碼就是一個線性布局裡麵包含2個按鈕加上一個顯示圖像的ImageView

在文件夾src下的com.testopencv.haveimgfun包中新建一個類用於包裝使用了opencv c++代碼的動態庫的導出函數,類名為LibImgFun。

Eclipse會為你創建一個新的文件LibImgFun.java,將裡面的內容改為:


1 package com.testopencv.haveimgfun;
2 public class LibImgFun {
3 static {
4 System.loadLibrary("ImgFun");
5 }
6 /**
7 * @param width the current view width
8 * @param height the current view height
9 */
10 public static native int[] ImgFun(int[] buf, int w, int h);
11 }


從上面的代碼可以得知,我們的動態庫名字應該為「libImgFun.so」,注意"public static native int[] ImgFun(int[] buf, int w, int h)"中的native關鍵字,表明這個函數來自native code。static表示這是一個靜態函數,這樣就可以直接用類名去調用。

在jni文件夾下建立一個"ImgFun.cpp"的文件,內容改為下面所示:


1 #include <jni.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <opencv2/opencv.hpp>
5 using namespace cv;
6
7 extern "C"
8 {
9 JNIEXPORT jintArray JNICALL Java_com_testopencv_haveimgfun_LibImgFun_ImgFun(JNIEnv* env, jobject obj, jintArray buf, int w, int h);
10 JNIEXPORT jintArray JNICALL Java_com_testopencv_haveimgfun_LibImgFun_ImgFun(JNIEnv* env, jobject obj, jintArray buf, int w, int h){
11
12 jint *cbuf;
13 cbuf = env->GetIntArrayElements(buf, false);
14 if(cbuf == NULL)
15 {
16 return 0;
17 }
18
19 Mat myimg(h, w, CV_8UC4, (unsigned char*)cbuf);
20 for(int j=0;j<myimg.rows/2;j++)
21 {
22 myimg.row(j).setTo(Scalar(0,0,0,0));
23 }
24
25 int size=w * h;
26 jintArray result = env->NewIntArray(size);
27 env->SetIntArrayRegion(result, 0, size, cbuf);
28 env->ReleaseIntArrayElements(buf, cbuf, 0);
29 return result;
30 }
31 }


上面的代碼中#include <jni.h>是必須要包含的頭文件,#include <opencv2/opencv.hpp>是opencv要包含的頭文件。

動態庫要導出的函數如下聲明:

JNIEXPORT jintArray JNICALL Java_com_testopencv_haveimgfun_LibImgFun_ImgFun(JNIEnv* env, jobject obj, jintArray buf, int w, int h);

JNIEXPORT 和JNICALL是必須要加的關鍵字

jintArray就是int[],這里返回類型要麼為空,要麼為jni中定義的類型,事實上就是CC++類型前面加上j,如果是數組,則在後面加上Array。

函數名的命名規則如下:

Java_(包路徑)_(類名)_(函數名) (JNIEnv *env, jobject obj, 自己定義的參數...)

包路徑中的"."用"_"(下劃線)代替,類名就是上麵包裝該動態庫函數的類的名字,最後一個才是真正的函數名;JNIEnv *env和jobject obj這兩個參數時必須的,用來調用JNI環境下的一些函數;後面就是你自己定義的參數。在這里,jintArray buf代表了傳進來的圖像的數據,int w是圖像的寬,int h是圖像的高。

這個函數的功能是將傳進來的圖像的上半部分塗成黑色。

然後再在jni下新建兩個文件"Android.mk"文件和"Application.mk"文件,這兩個文件事實上就是簡單的Makefile文件。

其中將Android.mk的內容改為如下所示:

LOCAL_PATH:=$(callmy-dir)

include$(CLEAR_VARS)

include../includeOpenCV.mk

ifeq("$(wildcard$(OPENCV_MK_PATH))","")

#trytoloadOpenCV.mkfromdefaultinstalllocation

include$(TOOLCHAIN_PREBUILT_ROOT)/user/share/OpenCV/OpenCV.mk

else

include$(OPENCV_MK_PATH)

endif

LOCAL_MODULE:=ImgFun

LOCAL_SRC_FILES:=ImgFun.cpp

include$(BUILD_SHARED_LIBRARY)

Application.mk的內容改為如下所示:

APP_STL:=gnustl_static

APP_CPPFLAGS:=-frtti-fexceptions

APP_ABI:=armeabiarmeabi-v7a

其中APP_ABI指定的是目標平台的CPU架構。(經過很多測試,android2.2必須指定為armeabi,android2.2以上的使用armeabi-v7a,如果沒有設置對,很有可能安裝到android虛擬機失敗,當然你同時如上面寫上也是可以的)

上面的步驟完成後,就可以使用NDK生成動態庫了,打開cygwin,cd到項目目錄下:


輸入$NDK/ndk-build命令,開始創建動態庫。


這時候刷新Eclipse的Package Explorer會出現兩個新的文件夾obj和libs。

現在,只剩最後一步完成這個測試程序。

將一張圖片,例如"lena.jpg"放到項目res->drawable-hdpi目錄中並刷新該目錄。

然後將HaveImgFun.java的內容改為下面所示:


1 package com.testopencv.haveimgfun;
2
3 import android.app.Activity;
4 import android.graphics.Bitmap;
5 import android.graphics.Bitmap.Config;
6 import android.graphics.drawable.BitmapDrawable;
7 import android.os.Bundle;
8 import android.widget.Button;
9 import android.view.View;
10 import android.widget.ImageView;
11
12 public class HaveImgFun extends Activity{
13 /** Called when the activity is first created. */
14 ImageView imgView;
15 Button btnNDK, btnRestore;
16
17 @Override
18 public void onCreate(Bundle savedInstanceState) {
19 super.onCreate(savedInstanceState);
20 setContentView(R.layout.main);
21
22 this.setTitle("使用NDK轉換灰度圖");
23 btnRestore=(Button)this.findViewById(R.id.btnRestore);
24 btnRestore.setOnClickListener(new ClickEvent());
25 btnNDK=(Button)this.findViewById(R.id.btnNDK);
26 btnNDK.setOnClickListener(new ClickEvent());
27 imgView=(ImageView)this.findViewById(R.id.ImageView01);
28 Bitmap img=((BitmapDrawable) getResources().getDrawable(R.drawable.lena)).getBitmap();
29 imgView.setImageBitmap(img);
30 }
31
32 class ClickEvent implements View.OnClickListener{
33 public void onClick(View v){
34 if(v == btnNDK){
35 long current=System.currentTimeMillis();
36 Bitmap img1=((BitmapDrawable) getResources().getDrawable(R.drawable.lena)).getBitmap();
37 int w=img1.getWidth(),h=img1.getHeight();
38 int[] pix = new int[w * h];
39 img1.getPixels(pix, 0, w, 0, 0, w, h);
40 int[] resultInt=LibImgFun.ImgFun(pix, w, h);
41 Bitmap resultImg=Bitmap.createBitmap(w, h, Config.RGB_565);
42 resultImg.setPixels(resultInt, 0, w, 0, 0,w, h);
43 long performance=System.currentTimeMillis()-current;
44 imgView.setImageBitmap(resultImg);
45 HaveImgFun.this.setTitle("w:"+String.valueOf(img1.getWidth())+",h:"+String.valueOf(img1.getHeight())+"NDK耗時"+String.valueOf(performance)+" 毫秒");
46 } else if(v == btnRestore){
47 Bitmap img2=((BitmapDrawable) getResources().getDrawable(R.drawable.lena)).getBitmap();
48 imgView.setImageBitmap(img2);
49 HaveImgFun.this.setTitle("使用OpenCV進行圖像處理");
50 }
51 }
52 }
53 }


點擊全部保存,OK,現在可以選擇一個Android虛擬機運行看一下效果,配置好Run Configuration然後點擊Run,得到下面的結果:

熱點內容
discuz友情鏈接緩存 發布:2024-11-24 19:00:11 瀏覽:693
資料庫時區 發布:2024-11-24 18:28:30 瀏覽:614
板的塑性演算法 發布:2024-11-24 18:17:59 瀏覽:29
酷狗緩存亂碼 發布:2024-11-24 18:12:42 瀏覽:509
aes演算法模式 發布:2024-11-24 17:47:19 瀏覽:612
linux查看埠是否佔用 發布:2024-11-24 17:42:15 瀏覽:467
手機電影天堂的文件夾 發布:2024-11-24 17:39:08 瀏覽:690
吉林金稅盤安全伺服器地址 發布:2024-11-24 17:39:00 瀏覽:277
360無法訪問網路 發布:2024-11-24 17:32:48 瀏覽:558
普通員工解壓拓展注意什麼細節 發布:2024-11-24 17:32:06 瀏覽:435