• 用csv文件读写一个人脸数据库,实现能够并显示对应的人脸结果


    写这篇博客背景是,前面博客中有说,最近正在做一个云端人脸识别的APP,之前写好了Java云端客户端,通信返回来的是一个512维的人脸向量。我这次的工作就是把向量存取到一个csv文件里面当做数据可来使用(其实使用JDBC技术调用数据库是最佳,但是为了简单先用的是csv代替),再写一个测试类遍历csv中的人脸向量,根据欧氏距算出得分值,再和某个阈值进行比对,如果小于那个阈值则返回我对应的人名,整个代码就是实现这样一个功能来的

    话不多说先直接上代码

    先把向量(浮点型集合数组)写进去csv文件中

    //定义一个写入流的操作类,用来把我通信中返回的人脸向量写进去

    public class CsvWrite {
    public static void main(String[] args) {

    //用一个浮点型集合来接受传回来的512维人脸向量,这个代码我就不贴了,涉及到我通信的代码
    List<Float> floatList = HttpChuanShu("C:\Users\rhp\Desktop\111\name2.jpg");
    String f = "C:\Users\rhp\Desktop\ceshi1.csv";

    //因为WriteFile接受的是String型参数,所以转换一下
    writeFile(f, floatList.toString());
    }

     

    public static void writeFile(String fileFullPath,String content) {

    //定义一个字节输出流
    FileOutputStream fos = null;
    try {
    //这里,我要说一下有点坑,我自己一开始选的构造方法中不带true的,这样我每次写进去,都会覆盖之前,以至于csv文件打开后只有一行,这里的true意思就是判断文件中可有内容,如果有,从内容的最后一行转换符下一行开始写入,就解决了被覆盖的问题
    fos = new FileOutputStream(fileFullPath, true);

    这里我为了在Eclipse开发,故意先用键盘输入来代替Android上面的人员主动注册留下的name
    Scanner sc = new Scanner(System.in);
    System.out.println("请输入保存的name");
    String name = sc.next();
    sc.close();

    //先写入名字
    fos.write(name.getBytes());
    //再写入内容,注意这点都是字节输入
    fos.write(content.getBytes());
    // 写入一个换行,上面已经写入成功了,但是注意,写进去的是一个字符串类型,下面读取流加计算欧氏距离时,需要装箱+切割得到你需要的浮点型数组
    fos.write(" ".getBytes());
    //加个日常的IO异常捕获操作
    } catch (IOException e) {
    e.printStackTrace();
    }finally{
    if(fos != null){
    try {
    fos.flush();
    fos.close();
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
    }
    }

     

    //这里写入就成功了,但是有个小问题我没有解决,就是,写进去第一行为空,默认从第二行开始读,我查阅了资料好像是csv默认第一行为表头信息,第一行为空在下面读写中会产生一个小问题,就是遍历字符串是,读到第一行null,会出现索引超出边界异常,所以你要想顺利遍历读取每一行,简单的操作就是直接手动删除第一行,这样就可以了

     

    //下面是读取操作并计算欧式距离输入对应的人名,这是我的功能目的

    public class CsvRead {

    public static void main(String[] args) {

    同理,先传入通信的浮点型集合
    List<Float> floatList = HttpChuanShu("C:\Users\rhp\Desktop\111\name1.jpg");
    String f = "C:\Users\rhp\Desktop\ceshi3.csv";

    //后面计算欧式距离需要,所以先定一个一个512大小的浮点型数组
    float[] a = new float[512];

    //遍历
    for (int i = 0; i < floatList.size(); i++) {
    a[i] = floatList.get(i);
    }

    }

     

    public static String CSV2Array(String path, float[] a) {
    try {

    定义好缓冲流去接受,编码这里用UTF-8
    BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(path), "UTF-8"));

    //定义一个String类型的变量line
    String line;
    // 定义一个全局变量,int类型i=0

    int i = 0;

    //循环遍历csv文件的每一行,知道读到的行内容为空跳出循环

    while ((line = in.readLine()) != null) {

    这里遍历字节,是为了取出每一行前面的name,为了后面输出对应的人的名字
    for (i = 0; i < 100; i++) {

    //因为我的每一行都是这样的类型   

    为了获取名字左后一个字节索引以便后面字符串截取名字用的

    if ('[' == line.charAt(i)) {
    System.out.println(i);

    //这里加一个中断,不想浪费资源,遍历到了我要的索引就跳出来就可以了
    break;
    }
    }

    定义一个名字的变量line1name,截取从0索引开始到刚遍历出来的那个索引结束,可以加一个打印看看,

    String line1name = line.substring(0, i);
    System.out.println(line1name);

    、、这里截取我要的字符串数组,把[ ]给除去
    String line1 = line.substring(i + 1, line.length() - 1);
    System.out.println(line1);

    //字符串split操作,因为上一步操作剩下来的是字符串,里面是有规律的,每个字符串数组以逗号分开,这也是csv默认的分隔符
    String[] a1 = line1.split(",");    //分割之后就是一个字符串数组了,你也可以打印看看长度,肯定是512维的数组,只不过类型现在还是字符串类型罢了
    System.out.println(a1.length);

    //计算欧氏距离,定义一个求和变量sum
    double sum = 0;

    //遍历字符串数组中每一个浮点型字符串
    for (; i < a1.length; i++) {

    //装箱操作,获取字符串浮点型对应的浮点值
    float a1f = Float.valueOf(a1[i]);

    //计算欧氏距离
    sum = Math.pow((double) (a1f - a[i]), 2) + sum;
    }
    System.out.println("sum: " + sum);

    //这是我设置的阈值,小于这个值返回return,终止while循环,输出对应的名字,否则一直遍历每一行,没有最终循环结束,返回null

    if (sum >= 1.24) {
    System.out.println("无法识别");

    } else {
    System.out.println("名字: " + line1name);
    in.close();
    return line1name;
    }
    }

    } catch (Exception e) {
    e.printStackTrace();

    }

    return null;

    }

     

     

     //哎,我是一个Java初学者,写的代码我相信稍微入门一点的都能轻易看明白,对自己而言也是更加熟悉,也是为了避免更多人和我一样进坑浪费大量时间,我看了网上很多博客,多而不实,真正完整的且实用的很少,自己每次找个资源也是百度一大片,差的还很远,慢慢学咯,嘻嘻

     

     

     

     

     

  • 相关阅读:
    41:和为S的两个数
    40:数组中只出现一次的数字
    39-2:平衡二叉树
    39:二叉树的深度
    38:数字在排序数组中出现的次数
    37:两个链表的第一个公共结点
    36:数组中的逆序对
    35:第一个只出现一次的字符
    34:丑数
    33:把数组排成最小的数
  • 原文地址:https://www.cnblogs.com/rhp2lmy1314/p/10942766.html
Copyright © 2020-2023  润新知