2020年8月2日日曜日

在 Android Studio 專案中導入 OpenCV

身為一個 Android BSP 工程師
不只是底層的 system bring up
或是 Linux kernel driver
又或是 HAL,NDK 串接
連上層 application 都要會呢 (´・ω・`)
真的變成名符其實的 Android 全端工程師了=v=

在 Android Studio 中使用 OpenCV for Android
這篇大概已經拖了2、3年了
一直都沒時間寫
然後每次要用就一直重蹈覆轍到處找資料= =
趁現在有時間趕快來寫一下

TL;DR

沒有...

安裝環境

  • Windows 10 1909
  • Android Studio 4.0.1
  • OpenCV 4.4.0

下載 OpenCV for Android

到 OpenCV 官網直接把 Android 版本的壓縮檔給抓下來
https://opencv.org/releases/

解壓縮

把壓縮檔裡面的這個資料夾解壓縮出來
因為這個資料夾的東西匯入專案之後就不重要了
所以隨便找個地方放就可以了

新增一個空專案

如果有舊的專案
這個步驟就直接略過就好

這邊選什麼 template 都可以
因為這個不會對接下來的動作造成影響


找個地方存放專案
然後語言看自己喜好就好
這邊用 kotlin 當示範
選好之後按 [Finish]


然後就會看到它自己開始安裝一些 components

完成之後就會看到專案了

這個時候有件很重要的事

等待它!!


因為這時候 Gradle 會開始下載一些套件跟同步整個專案
所以這個時候不等它的話
等等會出現一堆莫名其妙的錯誤!!
根據每台電腦跟網路的差異性
大約需要 1 ~ 30 分鐘不等的時間
同步完之後
就可以看到 log 裡出現跟下面這張圖差不多的東西了

匯入 OpenCV

[File]→[New]→[Import Module…]

然後就會跳出下面這個匯入用的框框

這邊有件事情很重要
剛剛解壓縮出來的路徑應該是
path/to/OpenCV-android-sdk

但是這邊要指定的 [Source directory]
是它的下一層的 [SDK] 資料夾

不然他會找不到東西的說= =
選完之後就 [Finish]

然後跟舊版的有些差異是
舊版的會需要輸入 [Module Name]
但是新的這個版本沒有地方輸入這個東西
所以等等就會產生一個很微妙的狀況
因為 Module Name 被自動設定成了
被指定的那個資料夾的名稱

所以等等這個 module 的名稱就變成了前面寫的 [SDK]

然後自動 sync 的時候就出現錯誤了Σ( ̄□ ̄|||)

這時候只要按下 error log 中
那行藍色提示安裝 NDK
就會自動跳出跟下面這張圖一樣的安裝畫面了

安裝完成之後按下那顆藍色的 [Finish] 按鈕
它就會自動開始同步專案了

然後根據電腦的效能會需要等個大概幾分鐘不等的時間

最後要在 log 中看到
CONFIGURE SUCCESSFUL 才算成功!!

然後在左上的 Project View 中
找到 [Android] 的字樣
通常專案的顯示預設是用 Android Project 來排列
不過這樣是看不到剛剛匯入的東西的!!
所以這時候要把 Project View 切換成 [Project]

切換完之後
就可以在下面的的 Project View 中
找到剛剛匯入的 [SDK] 資料夾了!!
這個東西就是剛剛匯入的 OpenCV 了!!

然後抱怨一下
以前舊版的還可以設定 module name 的時候
至少可以讓這個顯示的名字好看一點
現在這樣真的很難懂 = =

設定專案相依性

找到左上角的 [File]→[Project Structures…]

然後會跳出專案的設定

最左邊的 column 切換到 [Dependencies]
旁邊的 Modules 切換到 [app]
這邊的 [app] 是你的主要專案
所以有可能會不一樣

然後跟下圖一樣
按一下旁邊的 [+]
選到 [3 Module Dependency]

這時候就會看到跟下圖一樣的相依性追加畫面了
圖中的 [sdk] 就是剛剛匯入的 OpenCV
只是因為前面沒有設定名字
所以這邊根本看不出來他是什麼= =

然後把 [sdk] 打勾按 [OK]
這時候會回到剛剛的畫面
在畫面中的 [Dependency] 就會多了剛剛的 [sdk] 資料夾了

這時候按一下右下角的 [Apply]
然後就會看到跟下圖一樣的浮水印出現了
這時候 Gradle 會開始同步專案
沒意外的話同步完之後按藍色的 [OK] 離開

這時候會在 log 中看到 [CONFIGURE SUCCESSFUL]

到這邊基本上就設定完了!!

變更 compileSdkVersion (非必要)

這個步驟有點神奇
並不是一定要做
如果之後在 build 的時候都沒有出現問題的話
基本上這步可以不用做

不過之後 build 有出問題的話
可以考慮一下這個步驟

先把 Project View 切換回 [Android]
然後找到 Gradle Scripts
底下有個 build.gradle (Module: app)
然後把它打開來
找到 [compileSdkVersion] 這個數值
然後記得它

接著再打開 build.gradle (Module: sdk)
然後把這個的 compileSdkVersion 改成剛剛那個數字

這樣至少可以減少版本不同步的問題

測試

然後在 code 裡面加入測試用的 code

    if (!OpenCVLoader.initDebug()) {
        Log.i("OpenCV", "Failed");
    } else {
        Log.i("OpenCV", "Succeeded");
    }

直接 build …

沒意外的話
就會看到 [BUILD SUCCESSFUL]

這篇就這樣了

2019年10月17日木曜日

在 Ubuntu 18.04 上架設 GitLab

就像這篇的標題一樣
這篇主要是用來記錄怎麼架設 GitLab
GitLab 主要有 2 個版本
一個是 CE
一個是 EE
CE 是 Community Edition
EE 是 Enterprise Edition
因為 CE 不用錢
所以這篇裝的是 CE 版

TL;DR

安裝指令

sudo apt update
sudo apt upgrade -y
sudo apt install curl openssh-server ca-certificates postfix -y

curl -sS https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.deb.sh | sudo bash
sudo apt install gitlab-ce -y

設定

安裝完之後開啟 /etc/gitlab/gitlab.rb 這個檔案

sudo gedit /etc/gitlab/gitlab.rb

找到 external_url 這行
然後把 URL 寫進去
看起來會像下面這樣

external_url 'http://any.address'

然後讓 gitlab 做一次重新設定

sudo gitlab-ctl reconfigure

最後設定防火牆

sudo ufw allow ssh
sudo ufw allow http
sudo ufw allow https
sudo ufw enable

下面這行可以確認防火牆服務的狀態

sudo ufw status

就這樣沒了!!



硬體需求

根據官方文件描述

CPU 的部分

1 core supports up to 100 users but the application can be a bit slower due to having all workers and background jobs running on the same core
2 cores is recommended minimum number of cores and supports up to 100 users
4 cores supports up to 500 users
8 cores supports up to 1,000 users
32 cores supports up to 5,000 users

基本上如果有大於 5,000 使用者的需求
就需要做其他的設定來換取系統的效能
不過因為我用不到這麼多人的需求
所以就不考慮了

是說現在這個時間點也找不到一台 1 核心的電腦就是了
當然如果是用 VM 架的那就另當別論了...

記憶體的部分

4GB RAM + 4GB swap supports up to 100 users but it will be very slow
8GB RAM is the recommended minimum memory size for all installations and supports up to 100 users
16GB RAM supports up to 500 users
32GB RAM supports up to 1,000 users
128GB RAM supports up to 5,000 users

官方文件上是建議最少 8GB 啦
雖然它說 4GB 也可以
但是另外 4GB 是靠 swap 來運作的話基本上就慢了呀 @@
而且根據 repo 的大小有可能會需要更多或更少的記憶體
這就要看使用情況而定了

資料庫的部分

官方建議至少 5 ~ 10 GB
看需求而定
目前 12.1 以上的版本是支援 PostgreSQL
之前的 MySQL/MariaDB 建議是在升級之前移動到 PostgreSQL 去

支援的網頁瀏覽器

Firefox
Chrome/Chromium
Safari
Microsoft Edge
Internet Explorer 11
※不支援 JavaScript disabled 的環境

安裝

更新 package

反正在 ubuntu 上不管做什麼
只要用到 package 相依的東西就會要做這個動作
不過其實也不是這麼必要就是了
就自己選擇看要不要做就好...

sudo apt update
sudo apt upgrade -y

安裝相依套件

sudo apt install curl openssh-server ca-certificates postfix -y

安裝 GitLab

先追加 GitLab package repository

curl -sS https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.deb.sh | sudo bash

追加完之後先暫停一下
在執行安裝之前
要講一個東西叫做 EXTERNAL_URL
這個東西就是之後要被外部存取的 URL
依照官方文件的描述
要先指定這個變數再進行安裝
所以看起來會像下面這樣

sudo EXTERNAL_URL="https://gitlab.example.com" apt install gitlab-ce

但是如果這個時候還沒有要決定 url 的話也沒關係
就直接向下面這樣給他安裝也不會有問題

sudo apt install gitlab-ce -y

為什麼要把這個拿出來講的的原因是因為
我一開始沒有看文件就隨邊敲了個安裝指令
然後他就跳警告訊息了 =口=

不過這個值可以從檔案直接改所以也沒什麼影響就是了w
這個檔案是 /etc/gitlab/gitlab.rb
找個 editor 把這個檔案打開

sudo gedit /etc/gitlab/gitlab.rb

然後在裡面可以找到一行

external_url 

然後空空的東西
這邊就是可以填入 url 的地方
填完看起來會像下面這樣

external_url 'http://192.168.8.106'

這邊因為沒有要上 global 的需求
所以只給個 local ip 就可以了

然後就是跑一次 GitLab 的重新設定

sudo gitlab-ctl reconfigure

防火牆設定

這個沒設的話可能會沒辦法存取喔...
這裡用 ufw 來設定

sudo ufw allow ssh
sudo ufw allow http
sudo ufw allow https

然後啟動它

sudo ufw allow enable

檢查它的狀態

sudo ufw status

其他

HTTP server

是說因為 GitLab 本身已經內建 Nginx 了
所以原本如果有執行其他 httpd 的話可能會衝突
它的預設 port 是 80
如果已經有其他 web 也佔用了的話
這樣就要另外設定了!!

GitLab 的啟動跟停止

sudo gitlab-ctl stop
sudo gitlab-ctl start

2019年7月24日水曜日

Windows 10 的 WSL 中使用 Ubuntu 18.04 啟動 SSH 遇到的問題

在一般普通的 Ubuntu 底下
通常可以使用 systemd 來做 server management
但是 WSL 的 Ubuntu 有自己的 init system
所以基本上 systemctl 指令是沒有辦法使用的

遇到的問題

在敲下面這個 SSH 啟動的指令的時候就遇到了問題

sudo systemctl start sshd

解決的方法就是回歸最原始的 service 指令
sudo service ssh restart

不過事情好像沒那麼簡單 因為馬上就跳出了另外一個錯誤
Could not load host key: /etc/ssh/ssh_host_rsa_key
Could not load host key: /etc/ssh/ssh_host_ecdsa_key
Could not load host key: /etc/ssh/ssh_host_ed25519_key
 * Restarting OpenBSD Secure Shell server sshd
Could not load host key: /etc/ssh/ssh_host_rsa_key
Could not load host key: /etc/ssh/ssh_host_ecdsa_key
Could not load host key: /etc/ssh/ssh_host_ed25519_key

這時候只要敲一個指令就行了

sudo ssh-keygen -A

然後看到下面這個訊息就行了

ssh-keygen: generating new host keys: RSA DSA ECDSA ED25519

然後在重啟 ssh service

sudo service ssh restart

這時候會看到下面這行訊息就表示成功了

 * Restarting OpenBSD Secure Shell server sshd            [ OK ]

參考資料

Windows Subsystem for Linuxにssh接続する

2019年7月22日月曜日

YUYV 轉 RGB 的 C code

YUYV(YUV422) to RGB

YUYV to RGB

void yuyv_to_rgb(unsigned char* yuv,unsigned char* rgb, int image_width, int image_height)
{
    unsigned int i;
    unsigned char* y0 = yuv + 0;   
    unsigned char* u0 = yuv + 1;
    unsigned char* y1 = yuv + 2;
    unsigned char* v0 = yuv + 3;
 
    unsigned  char* r0 = rgb + 0;
    unsigned  char* g0 = rgb + 1;
    unsigned  char* b0 = rgb + 2;
    unsigned  char* r1 = rgb + 3;
    unsigned  char* g1 = rgb + 4;
    unsigned  char* b1 = rgb + 5;

    float rt0 = 0, gt0 = 0, bt0 = 0, rt1 = 0, gt1 = 0, bt1 = 0;
 
    for(i = 0; i <= (image_width * image_height) / 2 ;i++)
    {
        bt0 = 1.164 * (*y0 - 16) + 2.018 * (*u0 - 128); 
        gt0 = 1.164 * (*y0 - 16) - 0.813 * (*v0 - 128) - 0.394 * (*u0 - 128); 
        rt0 = 1.164 * (*y0 - 16) + 1.596 * (*v0 - 128); 
   
        bt1 = 1.164 * (*y1 - 16) + 2.018 * (*u0 - 128); 
        gt1 = 1.164 * (*y1 - 16) - 0.813 * (*v0 - 128) - 0.394 * (*u0 - 128); 
        rt1 = 1.164 * (*y1 - 16) + 1.596 * (*v0 - 128); 
      
        if(rt0 > 250)   rt0 = 255;
        if(rt0 < 0)     rt0 = 0; 
 
        if(gt0 > 250)  gt0 = 255;
        if(gt0 < 0) gt0 = 0; 
 
        if(bt0 > 250) bt0 = 255;
        if(bt0 < 0) bt0 = 0; 
 
        if(rt1 > 250) rt1 = 255;
        if(rt1 < 0) rt1 = 0; 
 
        if(gt1 > 250) gt1 = 255;
        if(gt1 < 0) gt1 = 0; 
 
        if(bt1 > 250) bt1 = 255;
        if(bt1 < 0) bt1 = 0; 
     
        *r0 = (unsigned char)rt0;
        *g0 = (unsigned char)gt0;
        *b0 = (unsigned char)bt0;
 
        *r1 = (unsigned char)rt1;
        *g1 = (unsigned char)gt1;
        *b1 = (unsigned char)bt1;
 
        yuv = yuv + 4;
        rgb = rgb + 6;
        if(yuv == NULL)
          break;
 
        y0 = yuv;
        u0 = yuv + 1;
        y1 = yuv + 2;
        v0 = yuv + 3;
  
        r0 = rgb + 0;
        g0 = rgb + 1;
        b0 = rgb + 2;
        r1 = rgb + 3;
        g1 = rgb + 4;
        b1 = rgb + 5;
    }   
}

usage

int image_width = 1920;
int image_height = 1080;
unsigned char * p_yuyv_data = (unsigned char *)malloc(sizeof(unsigned char) * image_width * image_height * 2);
unsigned char * p_rgb_data = (unsigned char *)malloc(sizeof(unsigned char) * image_width * image_height * 3);

// yuyv の処理
// ... 省略

yuyv_to_rgb(p_yuyv_data, p_rgb_data);

// rgb の処理
// ... 省略
free(p_yuyv_data);
free(p_rgb_data);

在 Ubuntu 18.04 make AOSP 8.1 遇到的錯誤

這陣子一直在搞 AOSP
但是 build AOSP 的時候好像很容易就出現錯誤了= =

TL;DR

$ export LC_ALL=C



遇到的錯誤訊息

flex-2.5.39: loadlocale.c:130: _nl_intern_locale_data: Assertion `cnt < (sizeof (_nl_value_type_LC_TIME) / sizeof (_nl_value_type_LC_TIME[0]))' failed.
Aborted (core dumped)
ninja: build stopped: subcommand failed.
ninja failed with: exit status 1




解決方法

$ export LC_ALL=C
locale 這個東西是用來設定執行的程式的不同語言環境用的
基本上包括了 Language、Territory、Codeset
locale 總共分成 12 類
所以有 12 個 define 值
LC_CTYPE
LC_NUMERIC
LC_COLLATE
LC_TIME
LC_MONETARY
LC_MESSAGES
LC_NAME
LC_ADDRESS
LC_TELEPHONE
LC_MEASUREMENT
LC_PAPER
LC_IDENTIFICATION
而 LC_ALL 的優先級別則高於上述的全部
所以設定 LC_ALL 的時候
就會完全不管上述的 locale sensitive 的設定
LC_ALL=C 的 “C” 指的是 POSIX
這意味著你的程式根本不管 locale 的設定
這樣就和多國語言的設計理念看起來有點衝突了的說= =

2019年7月21日日曜日

用 Android Studio 對 AOSP 進行除錯


這篇主要是要說
怎麼在 android studio 導入 aosp-based 的專案進行除錯
這篇拿 vamrs 的 rock960 的 android sdk 當範例

TL;DR

前提是這個專案已經 make 完了!!
$ cd ${project_root}
$ source build/envsetup.sh
$ mmm development/tools/idegen/
$ sudo development/tools/idegen/idegen.sh



需要的東西

  1. android studio
  2. 已經 make 過的 aosp-based project
因為這篇的重點是要除錯
所以一定要是 make 完的專案
如果只是要看 aosp 的 source 的話
基本上不需要 make 過的專案!!

執行環境設定

基本上只要能 make aosp-based project 就不需要在額外設定了
如果不行的話
也許可以參考之前寫的這篇:用 Ubuntu 18.04 建立 Android 系統建置環境

產生 idegen.jar

$ source build/envsetup.sh
$ mmm development/tools/idegen/

















產生的 idegen.jar 會在下面這個路徑裡
out/host/linux-x86/framework/idegen.jar
這個東西是用來等等要產生 android studio 用的 project config 用的
所以一定要確定這個東西有產生!!












產生 android.iml 和 android.ipr

有了剛剛產生的 idegen.jar 之後就可以產生 android studio 用的 config 了
而 android.iml 和 android.ipr 就是所謂的 project config 了
這時候只要執行 idegen.sh 就行了
$ development/tools/idegen/idegen.sh










怎麼可能呢...
事情竟然沒有這麼單純…@@
竟然被說沒有權限了!!
看了一下這個路徑還真的被劃了一個X...















加個 sudo 試試看
結果竟然可以了!!
$ sudo development/tools/idegen/idegen.sh





然後輸出的 android.iml 和 android.ipr 會在專案的根目錄下














導入 AOSP

接下來就輪到 android studio 出場了














選 [Open an existing Android Studio project]
然後找到剛剛的 android.ipr




















然後就跳出了個警告@@











然後直接選 [Convert] 就好
它不太會有什麼影響
接著就會看到整個專案被導入了













不對…
好像怪怪的=口=
仔細看了一下 IDE 底下的 log 才發現竟然出錯了@@
他說看起來剛剛產生的 iml 檔好像壞掉了( ´・д・)エッ
Load Settings: Cannot load settings from file 'android.iml'
最後看起來檔案好好的
只是因為 android studio 讀檔太慢了= =
所以不要緊張!!
它自己產生的 bug !!
幫它放置一段時間之後
它自己讀完就好了!!
它最後就會把整個專案讀進來了!!












這時候卻又報了一個警告
External file changes sync may be slow
The current inotify(7) watch limit is too low. More details.


讓我題外話一下
這個時候我突然想到一件事
前陣子在用 visual studio code 的時候
因為導入整個 linux kernel 5.x 全部的 source files
結果太大導致 VSC 吃不完
所以就調整了 fs.inotify 的監看數量















就是因為這個數值可能大了點…
所以換 android studio 抱怨檔案太多速度會變慢了=口=


結果 android studio 同步完整個專案花了超多時間地說OTL
就是 sync + indexing 大概花了 30 分鐘左右的時間
(i7-8559U + 16GB DDR4-3200 + Plextor m9peg 1TB)

設定 JDK

基本上如果只是要看 aosp 的 source 的話其實這個不太重要
不過因為要除錯
所以需要整個 framework 的 source 才行
不然它會去抓一些不是你想看的東西來用
這樣是沒辦法除錯的!!
打開 [File]->[Project Structures]
然後找到左邊 SDKs 的 Tab
按一下上面的 [+] 來新增一個 JDK












然後它會跳出一個對話框讓你選 JDK 的路徑
直接 [OK] 就好






















然後新增加出來的這個 jdk 的 [Name] 隨便取就好
那不太重要
可以認得出它就行了















然後找到下面的 Android API 28 Platform
把 Java SDK 選項換成剛剛新增的 JDK
















接著到左邊的 TAB 中找到 [Project Settings]->[Project]















把 剛剛新增加的 SDK 指定給現在這個 project















在旁邊的 TAB 找到 [Project Settings]->[Modules]
然後找到 [Dependencies]















把它們全部刪掉!!
但是要記得留下一些東西
像下面這張圖這樣















找到右邊的[+]
把 frameworks 和 external 兩個路徑給加進去












在追加路徑的時候
它會出現一個對話框
也是直接按[OK]就好




















加完之後看起來會像下面這張圖這樣















這時候 project tree 會在剛剛那兩個路徑後面顯示[library root]















然後就可以打開 source 下斷點進行除錯了!












大概就是這樣了(´∀`)ノシ