java表格识别PaddleOcr总结

往期关于表格提取

  1. java简单的表格识别
  2. 关于opencv提取表格的方式总结
  3. java-opencv再谈表格识别
  4. win下编译paddleocr方便java本地调用

简单总结下

  1. 前面写了些借助opencv实现表格的一些方法,但是内容识别我是用的paddleocr(我只是切割后识别,但是paddleocr其实识别结果是自带坐标的也就是说直接有表格识别的能力,但是这东西吧不能通用有些遇到问题还是需要个性化处理下)。
  2. opencv的win环境是官网下包就可以了,也可以自己编译。
  3. paddleocr的dll、so环境搭建文章前面也写了点(只不过win和linux都需要自己编译)。
  4. 借助于专业的模型处理有时候有时候也需要用opencv处理下的,另外paddleocr也有依赖opencv的地方。
  5. 如果是c++、python的话就可以直接开搞了,但是其他语言例如用java需要动态库,本篇简单说下dll代码吧(提前说下因为我碰到C++懵逼了,第一次我想到的是结果json序列化但是那个包引入有点麻烦我放弃了,然后我想的是直接返回识别结果JNA传递又没搞定,最后不想折腾了直接拼接字符串)。
  6. paddleocr也可以自己训练这个我不会。
  7. 生成dll还是其他一些操作可以借助AI给点实例参考。

cmake遇到得问题

  1. cmake我也不太熟悉但是好多需要编译的都需要用这个处理。
  2. cmake有些依赖github上的包clone不了,或者超时timeout(即使开了代理也不行)。然后把对应的makefile文件的https改为git,
java 复制代码
# GIT_REPOSITORY https://github.com/LDOUBLEV/AutoLog.git
  GIT_REPOSITORY git@github.com:LDOUBLEV/AutoLog.git

导出函数

写的有点啰嗦拼拼字符串只能说能跑

c++ 复制代码
__declspec(dllexport) char* VectorResult(char* image_dir);

char* VectorResult(char* image_dir) {
  std::vector<cv::String> cv_all_img_names;
  cv::glob(image_dir, cv_all_img_names);
  
    std::vector<cv::Mat> img_list;
    for (int i = 0; i < cv_all_img_names.size(); ++i) {
        cv::Mat img = cv::imread(cv_all_img_names[i], cv::IMREAD_COLOR);
        if (!img.data) {
            std::cerr << "[ERROR] image read failed! image path: "
                << cv_all_img_names[i] << std::endl;
            continue;
        }
        std::cerr << cv_all_img_names[i] << std::endl;
        img_list.push_back(img);
    }
    //这里可以获取到所有结果
    std::vector<std::vector<OCRPredictResult>> ocr_results = ocr.ocr(img_list, FLAGS_det, FLAGS_rec, FLAGS_cls);
    int size = ocr_results[0].size();
    std::string result;
    std::cout << size << std::endl;
    //OCRPredictResult* data = new OCRPredictResult [size];
    for (size_t i = 0; i < size; ++i) {
        std::string ret_str = (std::to_string(i)).append("|").append(ocr_results[0][i].text).append("|").append(std::to_string(ocr_results[0][i].score)).append("|").append(std::to_string(ocr_results[0][i].cls_label)).append("|").append(std::to_string(ocr_results[0][i].cls_score));
        //data[i] = ocr_results[0][i];
        for (auto j = 0; j != ocr_results[0][i].box.size(); ++j) {
            std::cout << ocr_results[0][i].box[j][0] <<" "<< ocr_results[0][i].box[j][1] << std::endl;
            ret_str.append("|").append(std::to_string(ocr_results[0][i].box[j][0])).append("|").append(std::to_string(ocr_results[0][i].box[j][1]));
        }
        //ret_str.append(";");
        result.append(ret_str.append("\r\n"));
    }
    //OCRRESUTL sv = { size, data };

    char* result2 = new char[result.size() + 1];
    strcpy(result2, result.c_str());
    return result2;
}

JNA复杂对象遇到的问题

  1. 我是直接用AI给的代码实例,但是里面有些头疼的问题就是这中间调用的过程不透明有些报错了摸不着头脑。
  2. 但是还有以下几个问题提前避免下。
  3. 复杂对象也就是对应c++里的结构体,但是里面给的类型需要注意例如vector我在网上看大部分也是处理为对应的结构体。
  4. java里面声明也很简单,但是注意属性应该用public不然参数指定顺序会报错的。
typescript 复制代码
@Override
protected List<String> getFieldOrder() {
    return Arrays.asList("box", "text", "score", "cls_score", "cls_label");
}
  1. 对象反序列化read/useMemory基类是protect类型的需要覆盖下,AI给的是直接调用方法的。
typescript 复制代码
@Override
public void read() {
   super.read();
}
@Override
public void useMemory(Pointer p) {
   super.useMemory(p);
}

paddleocr主要是这个日志包,下面是路径。

读光表格模型

读光表格分为有线和无线,如果用python的可以试下。网上应该是作者出了个onnx的版本,这个导出的模型没有默认长和宽这个需要注意下,另外模型转onnx后运算处理逻辑还是太复杂了(主要一些数学函数处理)java没有这方面的类库不好处理也试着用AI翻译下但还是放弃了。

AI大部分能用,但对于一些专业化小众的可能会有点问题,例如我上面遇到的两个问题。

相关推荐
罗曼蒂克在消亡43 分钟前
缓存的思考与总结
java·缓存·intellij idea
汇匠源43 分钟前
小程序服务零工市场
java·大数据·开发语言·小程序·团队开发·零工市场·零工市场小程序
2401_857297911 小时前
招联金融秋招内推喇--18薪
java·前端·算法·金融·求职招聘
xuchengxi-java2 小时前
SpringBoot Kafka发送消息与接收消息实例
spring boot·后端·kafka
一川死水2 小时前
JFinal整合Websocket
java·websocket·jfinal
小王不会写code2 小时前
Tomcat端口号被占用
java·tomcat·intellij-idea
OEC小胖胖2 小时前
MyBatis系统学习(四)——MyBatis的关联映射和缓存机制
java·后端·学习·缓存·mybatis·web
firepation2 小时前
SpringBoot - 基于 Java的超市进销存系统
java·spring boot·后端