前言
这是原作者的c++版本
其实最开始c++用着也蛮好的,可惜不甘于用adb,vs,bat组合起来对手机图片进行识别的苟且,毕竟坐那连着usb挺笨的,而且adb延迟有点高,所以就决定用手机实现图像识别。
难点主要在于网上各种教程的花里胡哨。
1、环境的配置(PS:被各种配置教程搞费了整整一天半的时间)
2、函数的迁移(对于初次接触opencv的人来说)
满打满算踩了一天半的坑,配置一天,移植半天。
关于android studio的opencv环境的配置
具体怎么配置就不详说了,毕竟是讲代码迁移的。
简单提一下。(搭配其他配置教程食用更佳)
(不用改makelist,也不用改gradle,没那么多花里胡哨,就这四步,但你至少得装上ndk,cmake,LLDB)
1、下载3.4.7的android opencv的sdk
2、import model 导入sdk
3、用app依赖刚导入的model
4、再把libs复制粘贴到你的工程里。
*5、已经能用了,但是会提醒你没有library信息,因为缺一个opencv_info.so,不用管他,是sdk版本导致的少东西的问题,没有info信息并不妨碍正常使用。
这里再说两点踏坑经验吧:
1、别一味追求新版本,Opencv SDK android版本的4.1.1的它少东西,配一年你也配不出来,别问我是怎么知道的。这里用的是3.4.7。(什么都喜欢最新的,然后终于栽了跟头)
2、对教程一定要持怀疑态度,有很多换汤不换药的毒教程,毒害你的时间和青春,因为一篇不明所以的教程,一直使用一个不能用的函数做测试,还以为是环境没有配好,浪费了很多时间。
一定能用的代码在此
//作者:零医一零
//时间:2019/10/27
//输入:两个位图
//输出:toast给你响应一下(响应在结尾自己改就是)
//个人习惯:情谊全在注释里
private void HashCompare( Bitmap Bp1, Bitmap Bp2) {
//数据定义导入部分
Mat src1 = new Mat();
Mat dst1 = new Mat();
Mat src2 = new Mat();
Mat dst2 = new Mat();
//读取位图到MAT
Utils.bitmapToMat(Bp1, src1);
Utils.bitmapToMat(Bp2, src2);
//变ARGB变灰度图,四通道变一通道
cvtColor(src1, dst1, Imgproc.COLOR_BGR2GRAY);
cvtColor(src2, dst2, Imgproc.COLOR_BGR2GRAY);
//把灰度图图缩成8*8
resize(dst1, dst1,new Size(8,8) , 0, 0, INTER_CUBIC);
resize(dst2, dst2,new Size(8,8) , 0, 0, INTER_CUBIC);
//核心算法部分
//这里变成二维数组才可以用Mat.get(row,cul)去获取,二维是因为每个像素点里面可能有很多属性(ARGB)
// 变成灰度之后就只有一个G了,这个G是Gray,前面那个G是Green。
double[][] data1 = new double[64][1];
double[][] data2 = new double[64][1];
//iAvg 记录平均像素灰度值,arr记录像素灰度值,data是个跳板。
int iAvg1 = 0, iAvg2 = 0;
double[] arr1 = new double[64];
double[] arr2 = new double[64];
//get灰度给data,用data给arr充值,算平均灰度值iAvg。
for (int i = 0; i < 8; i++)
{
int tmp = i * 8;
for (int j = 0; j < 8; j++)
{
int tmp1 = tmp + j;
data1[tmp1] = dst1.get(i,j);
data2[tmp1] = dst2.get(i,j);
arr1[tmp1] = data1[tmp1][0];
arr2[tmp1] = data2[tmp1][0];
iAvg1 += arr1[tmp1];
iAvg2 += arr2[tmp1];
}
}
iAvg1 /= 64;
iAvg2 /= 64;
//比对每个像素灰度值和平均灰度值大小
for (int i = 0; i < 64; i++)
{
arr1[i] = (arr1[i] >= iAvg1) ? 1 : 0;
arr2[i] = (arr2[i] >= iAvg2) ? 1 : 0;
}
//计算差异值
int iDiffNum = 0;
for (int i = 0; i < 64; i++)
if (arr1[i] != arr2[i])
++iDiffNum;
//输出什么看个人喜好
if (iDiffNum <= 5)
Toast.makeText(getBaseContext(), "真像", Toast.LENGTH_SHORT).show();
else
Toast.makeText(getBaseContext(), "我觉得不像", Toast.LENGTH_SHORT).show();
}