圖片二值化

新一版的需求中,加入了圖片二值化的處理,踩過坑,受過累,做一個標記,積累積累。。。



一、Android實現


    /**
     * 該函數實現對圖像進行二值化處理
     */
    public static Bitmap gray2Binary(Bitmap graymap) {
        //得到圖形的寬度和長度
        int width = graymap.getWidth();
        int height = graymap.getHeight();
        //創建二值化圖像
        Bitmap binarymap = null;
        binarymap = graymap.copy(Config.ARGB_8888, true);
        //依次循環,對圖像的像素進行處理
        for (int i = 0; i < width; i++) {
            for (int j = 0; j < height; j++) {
                //得到當前像素的值
                int col = binarymap.getPixel(i, j);
                //得到alpha通道的值
                int alpha = col & 0xFF000000;
                //得到圖像的像素RGB的值
                int red = (col & 0x00FF0000) >> 16;
                int green = (col & 0x0000FF00) >> 8;
                int blue = (col & 0x000000FF);
                // 用公式X = 0.3×R+0.59×G+0.11×B計算出X代替原來的RGB
                int gray = (int) ((float) red * 0.3 + (float) green * 0.59 + (float) blue * 0.11);
                //對圖像進行二值化處理
                if (gray <= 95) {//固定閾值
                    gray = 0;
                } else {
                    gray = 255;
                }
                // 新的ARGB
                int newColor = alpha | (gray << 16) | (gray << 8) | gray;
                //設置新圖像的當前像素值
                binarymap.setPixel(i, j, newColor);
            }
        }
        return binarymap;
    }

以Bitmap形式傳入數據,能夠實現二值化,輸出黑白圖片。

當前處理方式,設置固定閾值,會存在數據丟失情形。且使用Android自己的內存運算,運算速度較慢。



二、C實現【編譯so庫】

1,C代碼實現二值化

在C中比較好處理,且內存運算佔用較低,使用指針的方式。還可以將圖片的歸一化,旋轉等一些基礎的處理都添加到代碼中。


2,c代碼打包so庫

CmakeList打包so庫

嗯嗯,這是C打包so庫源碼

以下描述以下曾遇見的坑:

(1)不能編譯出來so庫

不能編譯出來so庫問題主要在兩個方面,一是c代碼存在bug或者內存泄漏,或者使用數據類型,Android編譯平臺不支持。


(2)編譯出來的so庫不能適配全平臺

編譯不能適配全平臺,主要在與配置環境參數的設置。

CmakeList設置C11

 cppFlags "-std=c++11" //, "-fuse-ld=bfd"

因爲C代碼中使用libpng版本比較老,在文章使用中,不能設置C11版本。

 cFlags '-std=c99', '-DPNG_ARM_NEON_OPT=0'


其他的配置,就按照CmakeList設置實現就可以。

三、細節實現注意點

1,adapter細節優化

 Log.e("getView", "getView    gridview  position=" + position + "parent child count=" + parent.getChildCount());


通過日誌的方式,可以確定第一個view重複了很多次。使用以下優化方案。

if (parent.getChildCount() == position || mViewItem0 == null) {
    if (mViewItem0 != null && position == 0) {
        return mViewItem0;
    }


//原始代碼實現方式實現

    if (position == 0) {
        mViewItem0 = convertView;
    }
} else {
    convertView = mViewItem0;
}


2,設置筆形方法優化

    public static HashMap<String, Typeface> mTypeface = new HashMap<>();//避免多次讀取ttf加載,Typeface佔空間很小

     if (ttfURL != null && !("".equalsIgnoreCase(ttfURL))) {
            if (mTypeface.get(ttfURL) == null) {
                File file = new File(ttfURL);
                if (file.exists() && file.length() > 0) {
                    mTypeface.put(ttfURL, Typeface.createFromFile(ttfURL));//文件存在是否需要判斷
                } else {
                    mTypeface.put("default", Typeface.createFromAsset(context.getAssets(), "FZKTJW.TTF"));
                }
            }
            setTypeface(mTypeface.get(ttfURL));
        } else {
            if (mTypeface.get("default") == null) {
                mTypeface.put("default", Typeface.createFromAsset(context.getAssets(), "FZKTJW.TTF"));
            }
            setTypeface(mTypeface.get("default"));
        }

3,onpageSelected(),設置adapter

(1)在ViewPager的onPageSelected()中不需要setCurrentItem(),當前已經是選中了,且不用notify。會消耗性能,導致運行緩慢。

(2)adapter默認會加載前後兩頁數據,設置前後深度切換效果後,也需要將前後兩頁數據加載出來。

singlePagePreVP.setPageTransformer(true, new DepthPageTransformer());
在新設置數據後,需要已緩存的三頁數據刷新時,使用notify()是不成功的。

直接設置adapter就可以,setAdapter(adapter);


這是二值化的效果。






只要你能健康的成長,正直的做人,獨立的思考,幸福的生活,這是父輩對你的最高期望。

發佈了121 篇原創文章 · 獲贊 32 · 訪問量 16萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章