批量从照片中提取文本

tesseract

识别率较低(已卸载)

安装

mac安装执行brew install tesseract即可,安装过程可能有点慢,要下载很久

安装完成后,执行brew info tesseract,可以查看tesseract相关信息

使用

1
2
3
4
5
6
tesseract <图片名字> <输出的文本文件名(自带.txt)> [-l 语言类型] [--oem ocrenginemode] [--psm pagesegmode] [configfiles...]
#举例
tesseract test.jpg stout -l chi_sim+equ --psm 6
ls
|-test.jpg
|-stout.txt

PaddleOCR

识别率高

安装

  1. pyCharm拉取github PaddlePaddle/PaddleOCR仓库的代码,并切换到分支release/2.7

  2. 在pyCharm终端执行下面命令,注意需要venv加载成功

    1
    2
    3
    4
    5
    6
    7
    #环境所需依赖
    (venv) ➜ PaddleOCR git:(release/2.7) pip install paddlepaddle
    (venv) ➜ PaddleOCR git:(release/2.7) pip install -U pip setuptools
    #安装
    (venv) ➜ PaddleOCR git:(release/2.7) pip install "paddleocr>=2.0.1"
    #使用
    (venv) ➜ PaddleOCR git:(release/2.7) paddleocr --image_dir /Users/xuanleung/Downloads/ppocr_img/imgs/11.jpg --use_gpu false

实战场景

有一大批照片,要从照片中获取指定信息作为图片的文件名,并根据文件名生产csv表格

  1. 提前训练好模型参考:PaddleSeg基于机器学习的图像分割

  2. 采用paddleSeg(模型预测)进行关键位置的识别

    1
    2
    #pycharm 运行 
    python tools/predict.py --config configs/quick_start/pp_liteseg_optic_disc_512x512_1k.yml --model_path output/iter_1000/model.pdparams --image_path /Users/x/Downloads/桩顶标高 --save_dir /Users/x/Downloads/桩顶标高out --custom_color 0 0 0 255 255 255
  3. 裁剪图片

    1
    2
    3
    #pycharm 运行 
    python tools/crop.py --input_mask_dir /Users/x/Downloads/桩顶标高out/pseudo_color_prediction --input_orig_dir /Users/x/Downloads/桩顶标高
    Creating crop directory: /Users/x/Downloads/桩顶标高/crop_dir
  4. 执行ocr识别,会产生一个output目录,里面会产生和图片对应文件名的txt文本,内容为ocr识别的内容

    1
    2
    3
    #建议优化脚本里面的识别方式,替换成PaddleOCR识别率提高非常的多
    #在图片所在目录
    bash ocr.sh
  5. 执行关键文字提取脚本,将关键字在文本文件里面保留

    1
    2
    #在图片所在的output目录里面
    bash format.sh
  6. 替换文件名,根据文本里面的内容作为图片的文件名

    1
    2
    #在图片所在目录
    bash rename.sh
  7. 根据文件名生产csv表格

    1
    2
    #在图片所在目录
    bash csv.sh

文件附录

  • ocr.sh:批量将当前脚本所在目录的图片转换成文本

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    #建议优化脚本里面的识别方式,替换成PaddleOCR识别率提高非常的多
    #!/bin/bash
    # 当前脚本所在目录
    script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
    # 输入文件夹路径为当前目录
    input_folder="$script_dir"
    # 输出文件夹路径为当前目录
    output_folder="$script_dir/output"
    # 创建输出文件夹
    mkdir -p "$output_folder"
    # 遍历输入文件夹中的所有图片文件
    for image_file in "$input_folder"/*.jpg "$input_folder"/*.png "$input_folder"/*.jpeg; do
    # 提取文件名(不含路径和扩展名)
    filename=$(basename "$image_file" | cut -f 1 -d '.')
    # 构建输出文本文件的路径
    output_text_path="$output_folder/$filename"
    # 执行 Tesseract 命令
    tesseract "$image_file" "$output_text_path" -l chi_sim+equ --psm 6
    echo "Processed $image_file"
    done
  • format.sh:批量将当前脚本所在目录的文本只保留关键信息

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    #!/bin/bash
    # 获取当前脚本所在目录
    script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
    # 遍历当前目录下的所有文本文件
    for file in "$script_dir"/*.txt; do
    # 检查文件是否存在
    if [ -f "$file" ]; then
    # 使用grep命令查找匹配行并提取信息
    transaction=$(grep -oE '体验[0-9]+' "$file" | cut -d'验' -f2)
    elevation=$(grep -oE '[0-9]{3}\.[0-9]{3}' "$file" | cut -d':' -f2)
    # 输出提取的信息
    echo "交易编号: $transaction"
    echo "高程: $elevation"
    # 将提取的信息写入原文件
    echo "$transaction-$elevation" > "$file"
    fi
    done
  • rename.sh:批量重命名脚本所在目录的图片,文件名根据output目录对应文件名的文本内容进行命名

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    #!/bin/bash
    # 获取当前脚本所在目录
    script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
    # 图片文件夹路径
    image_folder="$script_dir"
    # 遍历图片文件夹中的所有文本文件
    for text_file in "$image_folder"/output/*.txt; do
    # 检查文件是否存在
    if [ -f "$text_file" ]; then
    # 获取文本文件名(不含路径和扩展名)
    base_name=$(basename "$text_file" .txt)
    # 获取图片文件名
    image_file="$image_folder/$base_name.jpg"
    # 检查图片文件是否存在
    if [ -f "$image_file" ]; then
    # 获取文本文件的内容作为新的图片文件名
    new_name=$(cat "$text_file")
    # 检查是否有同名文件,如果有就给新名称添加序号
    new_image_file="$image_folder/$new_name.jpg"
    counter=1
    while [ -f "$new_image_file" ]; do
    new_image_file="$image_folder/${new_name}_${counter}.jpg"
    ((counter++))
    done
    # 重命名图片文件
    mv "$image_file" "$new_image_file"
    echo "Renamed '$image_file' to '$new_image_file'"
    fi
    fi
    done
  • csv.sh:根据文件名生产表格,表格数据有两列,文件名以-进行区分列

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    #!/bin/bash
    # 获取当前脚本所在目录
    script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
    # 图片文件夹路径
    folder="$script_dir"
    # CSV 文件路径
    csv_file="$script_dir/output.csv"
    # 创建 CSV 文件,并写入标题行
    echo "Column1,Column2" > "$csv_file"
    # 遍历文件夹中的所有图片文件
    for file in "$folder"/*.jpg; do
    # 提取文件名中的两个部分,使用 '-' 作为分隔符
    part1=$(basename "$file" | cut -d'-' -f1)
    part2=$(basename "$file" | cut -d'-' -f2 | sed 's/\.jpg//')
    # 将两个部分写入 CSV 文件
    echo "$part1,$part2" >> "$csv_file"
    done
  • crop.py:根据模型预测的数据,进行图片裁剪

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    # 参数:input_mask_dir 掩码图片目录,黑白图片
    # 参数:input_orig_dir 原始图片目录,文件名要和掩码图片文件名一致,后缀可以不一样
    # 输出:根据掩码图片裁剪原始图片,得到原图的裁剪图片
    import argparse
    import glob
    import os
    import os.path as osp
    import cv2

    from pathlib import Path
    from paddleseg.utils import logger

    def parse_args():
    parser = argparse.ArgumentParser(description='image crop.')
    parser.add_argument('--input_mask_dir', help='input annotated directory',type=str)
    parser.add_argument('--input_orig_dir', help='input annotated directory',type=str)
    return parser.parse_args()

    def main(args):
    output_dir = osp.join(args.input_orig_dir, 'crop_dir')
    if not osp.exists(output_dir):
    os.makedirs(output_dir)
    print('Creating crop directory:', output_dir) # 在原图目录创建裁剪后输出目录
    for mask_img in glob.glob(osp.join(args.input_mask_dir, '*.png')): # 遍历input_mask_dir目录所有png的图片
    print('read mask img from:', mask_img)
    mask_img_name = Path(mask_img).stem # 获取文件名
    print('read orig img name:', args.input_orig_dir+mask_img_name+".jpg")
    # 读取原始图像和关键部位掩码图像
    original_image = cv2.imread(args.input_orig_dir+"/"+mask_img_name+".jpg")
    mask_image = cv2.imread(mask_img, cv2.IMREAD_GRAYSCALE) # 假设是单通道的灰度图像
    # 查找掩码图像中的边界
    contours, _ = cv2.findContours(mask_image, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    # 找到最大的边界
    max_contour = max(contours, key=cv2.contourArea)
    # 获取最大边界的边界框
    x, y, w, h = cv2.boundingRect(max_contour)
    # 从原始图像中裁剪关键部位
    key_part = original_image[y:y + h, x:x + w]
    # 保存裁剪出的关键部位
    cv2.imwrite(output_dir+"/"+mask_img_name+".jpg", key_part)
    logger.info(f'crop img is saved in {output_dir}')

    if __name__ == '__main__':
    args = parse_args()
    main(args)