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大部分能用,但对于一些专业化小众的可能会有点问题,例如我上面遇到的两个问题。

相关推荐
尚学教辅学习资料6 分钟前
基于SpringBoot的医药管理系统+LW示例参考
java·spring boot·后端·java毕业设计·医药管理
雷神乐乐23 分钟前
File.separator与File.separatorChar的区别
java·路径分隔符
小刘|27 分钟前
《Java 实现希尔排序:原理剖析与代码详解》
java·算法·排序算法
逊嘘1 小时前
【Java语言】抽象类与接口
java·开发语言·jvm
morris1311 小时前
【SpringBoot】Xss的常见攻击方式与防御手段
java·spring boot·xss·csp
monkey_meng1 小时前
【Rust中的迭代器】
开发语言·后端·rust
余衫马1 小时前
Rust-Trait 特征编程
开发语言·后端·rust
monkey_meng1 小时前
【Rust中多线程同步机制】
开发语言·redis·后端·rust
七星静香1 小时前
laravel chunkById 分块查询 使用时的问题
java·前端·laravel
Jacob程序员1 小时前
java导出word文件(手绘)
java·开发语言·word