组件安装前提

  1. php8.0+
  2. 安装imagick扩展,
  3. 依赖bcmath 扩展

安装组件

    composer require wudg/pdf-images

组件使用

组件主要依赖 imagick 扩展来处理图片和 pdf 相关,若使用 hyperf 框架,pdf 转换图片速度会大大提升,默认使用 5 个携程来同时处理转换图片。


hyperf 框架使用

# 发布配置
php bin/hyperf.php vendor:publish wudg/pdf-images

# 注解模式调用
<?php
/**
 * Notes:
 * User: wudg <544038230@qq.com>
 * Date: 2025/12/03 16:57
 */

namespace App\Controller;
use Wudg\PdfImages\Engine\PdfImagesEngine;
use Hyperf\Di\Annotation\Inject;

class TestController extends AbstractController 
{
    #[Inject]
    private PdfImagesEngine $pdfImage;

    public function testPdfToImg() 
    {
        $pdfPath = BASE_PATH.'/test.pdf';
        $images = $this->pdfImage->pdfToImages($pdfPath);
        print_r($images);
    }
}

图片相关

pdf相关

  1. pdf 转换为图片
  2. 指定 pdf 页数替换图片
  3. 指定 pdf 页数图片合成
  4. 指定 pdf 页数添加文字

所有安装扩展的前提条件是你的环境 php 已经安装好,且 pecl 也已经安装

CentOS/RHEL 环境下

# 安装依赖
sudo yum install ImageMagick ImageMagick-devel

# 安装 PHP Imagick 扩展
sudo yum install php-imagick

# 或使用 pecl 安装
sudo yum install php-pear php-devel gcc
sudo pecl install imagick

# 启用扩展
echo "extension=imagick.so" | sudo tee /etc/php.d/imagick.ini

# 重启 PHP 服务
sudo systemctl restart php-fpm  # 如果使用 PHP-FPM
sudo systemctl restart httpd    # 如果使用 Apache

Ubuntu/Debian

# 安装依赖
sudo apt update
sudo apt install imagemagick libmagickwand-dev

# 安装 PHP Imagick 扩展
sudo apt install php-imagick

# 或使用 pecl 安装
sudo apt install php-pear php-dev build-essential
sudo pecl install imagick

# 启用扩展
echo "extension=imagick.so" | sudo tee /etc/php.d/imagick.ini

# 重启 PHP 服务
sudo systemctl restart php-fpm 

Alpine Linux

# 安装imagemagick
apk --update add imagemagick
# 安装依赖
apk add jpeg-dev libpng-dev freetype-dev imagemagick-dev

# 安装扩展
pecl install imagick

# 配置信息
cd /usr/local/etc/php/conf.d
vi docker-php-ext-imagick.ini
extension=imagick.so

macOS (Homebrew)

# 安装 ImageMagick
brew install imagemagick
# 安装 PHP Imagick 扩展
# 方法1: 使用 pecl(推荐)
pecl install imagick

# 启用扩展
# 编辑 php.ini 文件,添加:
extension="imagick.so"

# 重启 PHP 服务
brew services restart php 

安装前准备工作,提前安装好python需要的依赖包

# Ubuntu/Debian:
sudo apt update
sudo apt install -y make build-essential libssl-dev zlib1g-dev \
libbz2-dev libreadline-dev libsqlite3-dev wget curl llvm \
libncursesw5-dev xz-utils tk-dev libxml2-dev libxmlsec1-dev \
libffi-dev liblzma-dev


# CentOS/RHEL
sudo yum groupinstall -y "Development Tools"
sudo yum install -y gcc openssl-devel bzip2-devel libffi-devel \
zlib-devel readline-devel sqlite-devel ncurses-devel xz-devel \
tk-devel

# Alpine Linux
apk add --no-cache build-base libffi-dev openssl-dev \
bzip2-dev zlib-dev xz-dev readline-dev sqlite-dev \
ncurses-dev tk-dev

脚本安装pyenv

# 直接执行远程命令,国内机器需要耐心等待,也可以使用国内镜像操作
curl -fsSL https://pyenv.run | bash

# 国内镜像安装步骤
# 手动克隆镜像仓库
git clone https://gitee.com/mirrors/pyenv.git ~/.pyenv

# 配置环境变量 vim ~/.bashrc ,将下面代码放置最底部即可
export PYENV_ROOT="$HOME/.pyenv"
[[ -d $PYENV_ROOT/bin ]] && export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init - bash)"

# 重新加载配置
source ~/.bashrc

# 验证结果
pyenv --version

pyenv 使用

# 安装3.13.3版本,由于直接安装下载缓慢,使用清华镜像安装先把安装包下载到本地
wget https://mirrors.tuna.tsinghua.edu.cn/python/3.13.3/Python-3.13.3.tar.xz -P ~/.pyenv/cache/

# 安装3.13.3版本
pyenv install 3.13.3

系统要求

树莓派安装的为ubuntu系统

  • 系统版本:Linux wudg 6.14.0-1017-raspi #17-Ubuntu SMP PREEMPT_DYNAMIC Tue Oct 14 16:43:21 UTC 2025 aarch64 aarch64 aarch64 GNU/Linux
  • 硬件为树莓派4B 4c8g

模型选择和运行

由于配置较低,只能运行DeepSeek-R1-Distill-Qwen-1.5B-Q3_K_M.gguf 量化版本 Q3 ,测试速度 3~4token/s,速度不是很满意,但是能跑出结果,后续尝试使用 Q1 量化再试试,毕竟树莓派 cpu 计算能力较弱。

下载 gguf 的 deepseek 大模型文件

# 下载可能需要梯子,如果需要可以联系留言作者会私发给你
wget https://huggingface.co/deepseek-ai/DeepSeek-R1-Distill-Qwen-1.5B-GGUF/resolve/main/DeepSeek-R1-Distill-Qwen-1.5B-Q3_K_M.gguf -O DeepSeek-R1-Distill-Qwen-1.5B-Q3_K_M.gguf

编译llama.cpp 并运行

  • 下载 llama.cpp 源码,github 上没有编译好的适合树莓派 arm 架构的二进制,需要自行编译。llama.cpp 下载地址
  • 编译 llama.cpp ,可以根据文档自行编译,编译过程中可能会缺少一些类库文件,编译前提前安装好 cmake 等编译工具

    sudo apt-get install build-essential cmake libpthread-stubs0-dev libcurl4-openssl-dev
    
  • 编译时间预计在 10 分钟左右,编译成功后 会在 build/bin 下有对应的二进制文件可以用来执行 model 模型文件
  • 编译成功后直接运行

     # --host=0.0.0.0 局域网可访问,--port=8090 对外端口8090
     ./llama-server -m /home/admin/llm/model/DeepSeek-R1-Distill-Qwen-1.5B-Q3_K_M.gguf --host=0.0.0.0 --port=8090

python 要求和扩展安装

python版本 3.13.3,使用 venv 虚拟环境

安装 paddlepaddle & paddleocr 类库

pip install paddlepaddle==3.2.0 -i https://www.paddlepaddle.org.cn/packages/stable/cpu/
pip install "paddleocr[all]" -i https://pypi.tuna.tsinghua.edu.cn/simple

安装 pdf 转图片类库

pip install pdf2image -i https://pypi.mirrors.ustc.edu.cn/simple/

最终python核心扩展

Package                  Version
------------------------ -----------
llama_cpp_python         0.3.16
numpy                    2.3.4
pdf2image                1.17.0
pillow                   12.0.0
paddleocr                3.3.2
paddlepaddle             3.2.0
paddlex                  3.3.9

执行异常修复

  • 异常 ImportError: libGL.so.1: cannot open shared object file: No such file or directory,可运行如下指令安装对应类库解决

     sudo apt-get install -y libgl1 libglib2.0-0 libsm6 libxrender1 libxext6

最终实现

    from paddleocr import PaddleOCR
    from pdf2image import convert_from_path
    pdfPath = './tst_contact.pdf'
    import time

    start = time.time()
    images = convert_from_path(pdfPath, dpi=80)

    ocr = PaddleOCR(
        text_detection_model_name='PP-OCRv5_mobile_det',
        text_recognition_model_name='PP-OCRv5_mobile_rec',
        use_doc_orientation_classify=False,
        use_doc_unwarping=False,
        enable_mkldnn=True,
        device='cpu',
        cpu_threads=4,
        use_textline_orientation=False) # 文本检测+文本识别

    all_texts = []
    # 保存所有页面
    for i, image in enumerate(images):
        imagePath = f'page_{i+1}.png'
        image.save(imagePath, 'PNG')
        print("正在分析 "+ imagePath)
        result_generator = ocr.predict_iter(imagePath)
        for page_result in result_generator:
            all_texts.append(page_result['rec_texts'])

    from llama_cpp import Llama
    flat_texts = [line for page in all_texts for line in page]
    full_text = "\n".join(flat_texts)
    prompt = f"""
    根据以下文本
    {full_text}
    请帮我提取被许可人姓名(name),姓名拼音(namePy),地址(address),协议开始时间(startTime),协议时间(endTime),服务费(rentAmount),付款方式(rentType),保证金金额(otherMmount),注册费(regAmount),总服务费(totalAmount) 等信息,没有相关内容可以为空。json格式返回,括号为 json 的key 值
    """
    print(prompt)
    model_Path = '/home/llm/model/DeepSeek-R1-Distill-Qwen-1.5B-Q8_0.gguf'
    llm = Llama(
        model_path=model_Path,
        n_ctx=2048,  # 上下文长度
        n_threads=4  # CPU线程数
    )
    output = llm(
        prompt,
        max_tokens=2048,
        echo=True
    )
    print(output['choices'][0]['text'])
    end = time.time()
    print("总执行时间:", end - start, "秒")

最终执行合同消耗时间在 130 秒左右,效果不是 很好,看来树莓派不适合跑大模型, 后续部署在 4c/8g 的阿里云机器上 大模型使用线上 api 方式调用 提升很明显,一个 5 页合同能在 20 秒内返回结果

文件操作


# 宿主机copy文件到指定docker容器中,将source.zip 复制到elastcisearch容器中的/usr/share/elasticsearch/plugins 目录下

docker cp source.zip elasticsearch:/usr/share/elasticsearch/plugins


# 从容器内复制内容到宿主机,将elasticsearch 容器中的:/usr/local/tomcat/webapps/test/js/test.js 文件复制到宿主机的/opt 目录下
docker cp elasticsearch:/usr/local/tomcat/webapps/test/js/test.js /opt

容器相关操作



# 打包修改后的容器
# -a 提交的镜像作者;
# -m 提交时的说明文字
docker commit -a "runoob.com" -m "my apache" 0bd244689ed2 mymysql:v1

网络自定义

# 创建自己的网络桥段【cgls】
docker network create --driver bridge --subnet=172.16.12.0/16 --gate=172.16.1.1 mebei_bridge


# 查看网络桥段【bridge】的信息
docker network inspect bridge

查看容器内网ip

docker inspect [容器名称]
docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' [容器名称]

上传至 hub.docker.com

  • 仓库路径 https://hub.docker.com
  • username : xxx
  • password: xxx

    
    # 基于已有的docker 创建自己的docker 镜像
    
    docker commit [container_id] [new_image_name]
    
    egg: docker commit 698 learn/ping
    
    
    # 推送至 dockerhub 中
    docker push wudg/php74:latest
    

docker镜像地址

"registry-mirrors": [
    "docker.hpcloud.cloud",
    "docker.m.daocloud.io",
    "docker.unsee.tech",
    "docker.1panel.live",
    "mirrors.ustc.edu.cn",
    "docker.chenby.cn",
    "mirror.azure.cn",
    "dockerpull.org",
    "dockerhub.icu",
    "hub.rat.dev"
]