本系列整理常用圖像處理算法的 JNI 實現,輸入輸出均為 int[] 像素數組(ARGB_8888),適用於 Android NDK 開發。NDK r22+ 已提供 Bitmap.h 直接操作 Bitmap 物件,本文採用兼容性更廣的數組傳遞方式。
原理:目標像素 (i+u, j+v) 由源圖四鄰域 (i,j)、(i+1,j)、(i,j+1)、(i+1,j+1) 加權平均得到。
公式:f(i+u,j+v) = (1-u)(1-v)f(i,j) + (1-u)v f(i,j+1) + u(1-v)f(i+1,j) + uv f(i+1,j+1)
實現要點:分通道插值(A/R/G/B 獨立計算再合成),邊界處理用 min(idx+1, max-1) 防越界。
// 核心混合函數
int mixColor(int *c, int i, int j, float u, float v) {
int a = mixARGB(c, i, j, u, v, alpha);
int r = mixARGB(c, i, j, u, v, red);
int g = mixARGB(c, i, j, u, v, green);
int b = mixARGB(c, i, j, u, v, blue);
return (a<<24) | (r<<16) | (g<<8) | b;
}
標準公式:Gray = 0.299R + 0.587G + 0.114B(ITU-R BT.601)。
定點化優化:避免浮點運算,採用移位近似。16 位精度下 7 位係數最優:
Gray = (R*38 + G*75 + B*15) >> 7
遊戲場景常用 2 位係數 (R*1 + G*2 + B*1) >> 2,速度最快且視覺差異可忽略。
原理:最大類間方差法,遍歷 0-255 灰度閾值,計算前景/背景像素佔比 w0/w1 及平均灰度 u0/u1,最大化 g = w0*w1*(u0-u1)²。
優勢:全局單一閾值,計算量固定(256 次循環),適合光照均勻圖像。
代碼結構:統計直方圖 → 累積計算 w0/u0 → 推導 w1/u1 → 計算 g → 記錄最大 g 對應閾值。
int otsu(jint *pixels, int w, int h) {
uint32_t hist[256] = {0};
// 統計直方圖
for (int i=0;i g_max) { g_max = g; thresh = k; }
}
return thresh;
}
下篇將覆蓋:幾何變換(旋轉/鏡像/透視)、卷積濾波(銳化/模糊/邊緣檢測)、直方圖均衡化、形態學操作(膨脹/侵蝕/開閉運算)。