最近应用在使用zxing进行二维码扫描时,发现对于金属质地,黑色凹槽的二维码识别率非常低且耗时很长,所以就有了探究二维码识别原理的想法。
正文
先灰度化再二值化是图片识别非常重要的一步,能够方便的提取图片特征。
原理是,将图片的灰度设定一个阈值,高于这个阈值的点变为黑色,低于这个阈值的点变为白色,这样能很方便的判断图片特征。
通用的灰度公式是:gray=r*0.3+g*0.59+b*0.11
获取颜色的argb方式:
alpha=color >>> 24
red=(color >> 16) & 0xFF
green=(color >> 8) & 0xFF
blue=color & 0xFF
生成颜色的方式:color=(alpha << 24) | (red << 16) | (green << 8) | blue
获取图片的color信息:
Bitmap对象.getPixels(@ColorInt int[] pixels, int offset, int stride,int x, int y, int width, int height)
写入图片的color信息:
Bitmap对象.setPixels(@ColorInt int[] pixels, int offset, int stride,nt x, int y, int width, int height) 方法:用数组中的颜色替换位图中的像素。
完整代码:
public static Bitmap singleThreshold(final Bitmap bm,int digit) {
int width = bm.getWidth();
int height = bm.getHeight();
int color;
int r, g, b, a;
Bitmap bmp = Bitmap.createBitmap(width, height
, Bitmap.Config.ARGB_8888);//创建一个图片对象
int[] oldPx = new int[width * height];
int[] newPx = new int[width * height];
bm.getPixels(oldPx, 0, width, 0, 0, width, height); //获取图片的颜色像素
for (int j = 0; j < width * height; j++) {
//获取单个颜色的argb数据
color = oldPx[j];
r = Color.red(color);
g = Color.green(color);
b = Color.blue(color);
a = Color.alpha(color);
//计算单点的灰度值
int gray = (int)((float)r*0.3+(float)g*0.59+(float)b*0.11);
//根据阈值对比,低于的设置为黑色,高于的设置为白色
if(gray < digit) {
gray = 0;
} else {
gray = 255;
}
newPx[j] = Color.argb(a,gray,gray,gray);
}
bmp.setPixels(newPx, 0, width, 0, 0, width, height);
return bmp;
}