圖形圖像處理 - Android 濾鏡效果

年初來深圳正式開始從事音視頻開發,為啥我想從事音視頻開發呢?有一個簡單的理由是我想建立起自己的技術壁壘,別人不能做的你能做,別人解決不了的你能解決。我們工作多年甚至于做了幾十個項目,如果我們不能從項目中去學習新的東西,那技術就只能停滯不前了。當然有哥們建議我說,你學的東西太多了但是不精,因此同樣我也建議大家還是先把 Java 基礎和 Android 基礎打牢。后面我將寫下一些圖形圖像處理的文章,很多是我自己學來的,也有些是我工作中遇到的。感興趣的哥們可以看下,也希望可以幫大家少走一些彎路。文章和視頻主要還是以 NDK 為主,因此希望各位看官能有一些 c 和 c++ 的基礎,有一些數據結構和算法的基礎,如果沒有建議大家去看看我之前寫的一些文章。

1. OpenCV 安裝

OpenCV 是一個計算視覺的開源庫,主要算法涉及圖像處理和機器學習。是 Intel 公司貢獻出來的,因為它可以免費應用在商業和研究領域,且國內大多數圖像處理相關的應用程序中都采用的是 OpenCV,因此后面很大一部分內容我們都基于 OpenCV 來講。官方給我們封裝了很多 java 層的接口,但總的來說可擴展性不是很高,因此后面我們主要采用 c++ 來寫,然后自己編譯成 so 庫來供 Android 調用。為了便于方法和算法的講解,我們暫時基于 VS 環境來編寫代碼,大家如果用的是 mac 電腦,可以去看看我之前的《NDK開發前奏 - 實現支付寶人臉識別功能》 ,也可以直接基于 android 環境開發。接下來我們一步步來搭建 VS 的開發環境:

首先我們找到 opencv 的官網 https://opencv.org/opencv-4-0-0-rc.html ,目前最高版本是 4.0 點擊 Win pack 進行下載。下載下來是一個 exe 文件,我們不要安裝直接解壓就好。找到 build\x64\vc14\bin 下,把目錄進行拷貝配置環境變量:

環境變量配置

然后新建 VS 空項目,找到菜單欄的 調試窗口 -> 屬性 -> 配置屬性 -> VC++ 目錄


在包含目錄和庫目錄中新增我們 opencv 的解壓目錄。然后我們寫一個簡單實例測試能即可:

#include <opencv2/opencv.hpp>
#include <iostream>

using namespace cv;

void main(){
    // 本地讀取一張圖片
    Mat src = imread("C:/Users/hcDarren/Desktop/android/NDK/NDK_Day56/test1.jpg");
    Mat gray;
    // 轉灰度
    cvtColor(src, gray, COLOR_BGR2GRAY);
    // 將灰度圖顯示到窗口
    namedWindow("test pic",CV_WINDOW_NORMAL);
    imshow("test pic", gray);
    waitKey(0);
}

大家按照我這個配置去做,可能還是會遇到很多問題。但所有的問題都離不開兩個方面,一個是頭文件,一個是實現的 dll 動態庫。

2. Android 濾鏡效果

我們來看一個比較常見同時也是非常簡單的例子,打開 QQ 空間發說說圖片時會有一個濾鏡功能,我們可以自己先去看看那些濾鏡效果。

實現這樣的效果有多種方案,Java 層用 ColorMatrix 矩陣來實現,Java 層操作 Bitmap 像素,Native 層操作 Bitmap 像素指針等等。這里我把三種方案都寫上,希望大家能夠做到舉一反三。以彩色圖轉灰度圖為例:

2.1 Java 層用 ColorMatrix 矩陣來實現

    public static Bitmap gary(Bitmap bitmap) {
        Bitmap gary = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), bitmap.getConfig());
        Canvas canvas = new Canvas(gary);
        Paint paint = new Paint();
        // 比較流行的方法。幾個加權系數0.3,0.59,0.11是根據人的亮度感知系統調節出來的參數,是個廣泛使用的標準化參數
        ColorMatrix colorMatrix = new ColorMatrix(new float[]{
                0.30f, 0.59f, 0.11f, 0, 0,
                0.30f, 0.59f, 0.11f, 0, 0,
                0.30f, 0.59f, 0.11f, 0, 0,
                0, 0, 0, 1f, 0
        });
        ColorMatrixColorFilter colorFilter = new ColorMatrixColorFilter(colorMatrix);
        paint.setColorFilter(colorFilter);
        canvas.drawBitmap(bitmap, 0, 0, paint);
        return gary;
    }

2.2 Java 層操作 Bitmap 像素

    public static Bitmap gary(Bitmap bitmap) {

        int[] pixels = new int[bitmap.getWidth() * bitmap.getHeight()];
        bitmap.getPixels(pixels, 0, bitmap.getWidth(), 0, 0, bitmap.getWidth(), bitmap.getHeight());

        for (int i = 0; i < pixels.length; i++) {
            int pixel = pixels[i];
            int a = (pixel >> 24) & 0xff;
            int r = (pixel >> 16) & 0xff;
            int g = (pixel >> 8) & 0xff;
            int b = pixel & 0xff;

            int gery = (int) (0.30f * r + 0.59f * g + 0.11f * b);
            pixels[i] = (a << 24) |  (gery << 16) |  (gery << 8)  |  gery;
        }

        Bitmap gary = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), bitmap.getConfig());
        gary.setPixels(pixels, 0, bitmap.getWidth(), 0, 0, bitmap.getWidth(), bitmap.getHeight());

        return gary;
    }

2.3 Native 層操作 Bitmap 像素指針

extern "C"
JNIEXPORT void JNICALL
Java_com_ndk_day51_BitmapUtil_gary(JNIEnv *env, jclass type, jobject bitmap) {
    // 獲取 Bitmap 信息
    AndroidBitmapInfo bitmapInfo;
    AndroidBitmap_getInfo(env, bitmap, &bitmapInfo);

    // 鎖定畫布
    void *pixels;
    AndroidBitmap_lockPixels(env, bitmap, &pixels);

    for (int i = 0; i < bitmapInfo.width * bitmapInfo.height; ++i) {
        uint32_t *p_pixel = reinterpret_cast<uint32_t *>(pixels) + i;
        uint32_t pixel = *p_pixel;
        int a = (pixel >> 24) & 0xff;
        int r = (pixel >> 16) & 0xff;
        int g = (pixel >> 8) & 0xff;
        int b = pixel & 0xff;
        int gery = r * 0.3f + g * 0.59f + b * 0.11f;
        *p_pixel = (a << 24) | (gery << 16) | (gery << 8) | gery;
    }
    
    // 解鎖畫布
    AndroidBitmap_unlockPixels(env, bitmap);
}

如果我們不是很了解矩陣的操作,可以去 Google 查查資料。上面的代碼也還會有些許問題,如果我們想用到項目中還得好好思考思考。

視頻地址:https://pan.baidu.com/s/1FqGwalxQimTwfoMKvIZNXw
視頻密碼:5xnx

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,786評論 6 534
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,656評論 3 419
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,697評論 0 379
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,098評論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,855評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,254評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,322評論 3 442
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,473評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,014評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,833評論 3 355
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,016評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,568評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,273評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,680評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,946評論 1 288
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,730評論 3 393
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,006評論 2 374

推薦閱讀更多精彩內容

  • 用兩張圖告訴你,為什么你的 App 會卡頓? - Android - 掘金 Cover 有什么料? 從這篇文章中你...
    hw1212閱讀 12,793評論 2 59
  • 在Android開發中,一般對圖像的處理就是Bitmap(位圖),它包含了圖像的全部數據,即點陣和顏色值,點陣就是...
    李晨瑋閱讀 8,018評論 1 33
  • 今天老師帶我們去了糖酒會,但是我們好像被當成了免費的勞動力,幫著老師讓參展商填問卷,問卷一個小組就300份,期間還...
    skymemory7閱讀 376評論 0 0
  • 1 小時候,父親煮過一道菜:蒜子蒸鉗魚。那個蒜頭,一瓣一瓣的,蒸熟了出來,沒有了蒜的難聞的氣味,吃起來松松軟軟,還...
    小螢子閱讀 665評論 2 0
  • 5:15分,鬧鐘準時想起,起床嘍!穿上跑鞋,就感覺自己元氣滿滿! 這一段時間,淅淅瀝瀝的秋雨纏纏綿綿。歇了幾天的身...
    谷子_8e39閱讀 475評論 11 11