pdf转图片,nodejs图片切割、opencv处理图片灰度,批量扫描二维码

项目场景:

需求:公司做会员卡实体卡的项目,需要扫码绑定用户,制卡商给了一个pdf文件里面包含2000张会员卡要求确认印刷,需要扫描出二维码内容并确定


问题描述

这个任务被安排到我身上(本人前端),领导让手动扫码,作为一个程序员怎么可能干这么蠢的事呢,想着写个脚本解决一下,以下为解决步骤:

1. 首先要把pdf的每一页分开

有一个很方便的网站 iLovePDF | Online PDF tools for PDF lovers可以在线把pdf转为图片

2. 把每个卡分成一个图片文件

这里我用node写了个脚本把图片平均分为五行五列,就实现了每个图片上有一个二维码

const fs=require('fs');
const sharp=require('sharp');


const filesArr=fs.readdirSync('./ilovepdf_pages-to-jpg');



for (let i=0; i<filesArr.length; i++) {
  const fileName=filesArr[i];
  const inputImagePath='./ilovepdf_pages-to-jpg/'+fileName;
  // 设置输入图片路径和输出文件夹路径
  const outputFolderPath='./output_images';
  // 读取输入图片数据
  const imageBuffer=fs.readFileSync(inputImagePath);
  // 创建输出文件夹
  if (!fs.existsSync(outputFolderPath)) {
    fs.mkdirSync(outputFolderPath);
  }

  // 设置分割参数
  const numRows=5; // 分割行数
  const numCols=5; // 分割列数
  const imgHandle=async () => {

    const imageInfo=await sharp(imageBuffer).metadata();

    const imageHeight=imageInfo.height;
    const imageWidth=imageInfo.width;
    const blockWidth=Math.floor(imageWidth/numCols);
    const blockHeight=Math.floor(imageHeight/numRows);
    // 分割图片
    for (let row=0; row<numRows; row++) {
      for (let col=0; col<numCols; col++) {
        const x=col*blockWidth;
        const y=row*blockHeight;

        sharp(imageBuffer)
          .extract({ left: x, top: y, width: blockWidth, height: blockHeight })
          .toFile(`${outputFolderPath}/${i}_${row}_${col}.png`, (err) => {
            if (err) {
              console.error(`Error saving ${i}_${row}_${col}.png:`, err);
            } else {
              console.log(`Saved ${i}_${row}_${col}.png`);
            }
          });
      }
    }
  }
  imgHandle()
}

3. 扫描二维码

这里我又写了个脚本

const fs=require('fs');
const resultFilePath='./multi_qr_results.txt';
const failFilePath='./fail.txt';

const filesList=fs.readdirSync('./output_images')

let num=0

var jsqr=require('jsqr');
var Jimp=require('jimp');


filesList.forEach((item, index) => {
  var buffer=fs.readFileSync('./output_images/'+item);
  Jimp.read(buffer).then(function (blockimg) {
    var width=blockimg.bitmap.width,
      height=blockimg.bitmap.height,
      imgData=blockimg.bitmap.data;
    var code=jsqr(imgData, width, height,'invertFirst');
    if (code) {
      console.log(code.data);//内容
      fs.appendFileSync(resultFilePath, `${item}: ${code.data},\n`);
      //       successObj.item = code.data

    } else {
      console.log('未识别成功')
      //       failArr.push(item)
      fs.appendFileSync(failFilePath, `${item},\n`);
    }
  }).catch(function (err2) {
    if (err2) {
      console.log(err2);
      cb(null, null);
    }
  });
})

4. 出现意外

到这里假如二维码清晰已经完成了,由于二维码的背景是个卡片,并且对比度不高,只扫出了三分之二,想着把图片处理以下

5. 解决意外

这里我又写了个脚本(用了python,现学现卖)

import cv2
import imutils
from skimage import measure
import numpy as np
import os

# 设置输入目录和输出目录
input_directory = './output_images'  # 输入目录,包含图片的目录
output_directory = 'gray_img'  # 输出目录,保存处理后的图片的目录
# 创建输出目录
if not os.path.exists(output_directory):
    os.makedirs(output_directory)

# 获取输入目录中所有的图片文件
image_files = [f for f in os.listdir(input_directory) if f.lower().endswith(('.png', '.jpg', '.jpeg'))]
for image_file in image_files:
    input_path = os.path.join(input_directory, image_file)
    output_path = os.path.join(output_directory, image_file)
    # 读取图像
    image = cv2.imread(input_path)
    image = cv2.resize(image, (1500, 1000))
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    #ret, binary = cv2.threshold(gray, 135, 255, cv2.THRESH_BINARY)
    cv2.imwrite(output_path, gray)

6.然后稍微改下之前的脚本,只处理未成功的图片

大功告成!

const fs=require('fs');
const resultFilePath='./chenggong.txt';
const failFilePath='./shibai.txt';

const filesList=fs.readdirSync('./output_images')

var jsqr=require('jsqr');
var Jimp=require('jimp');

let failArr=[
'0_1_2.png',
'10_1_2.png',
]

console.log(failArr.length);
// return

failArr.forEach((item, index) => {
  var buffer=fs.readFileSync('./gray_img/'+item);
  Jimp.read(buffer).then(function (blockimg) {
    var width=blockimg.bitmap.width,
      height=blockimg.bitmap.height,
      imgData=blockimg.bitmap.data;
    var code=jsqr(imgData, width, height,'invertFirst');
    if (code) {
      console.log(code.data);//内容
      fs.appendFileSync(resultFilePath, `${item}: ${code.data},\n`);
    } else {
      console.log('未识别成功')
      fs.appendFileSync(failFilePath, `${item},\n`);
    }
  }).catch(function (err2) {
    if (err2) {
      console.log(err2);
      cb(null, null);
    }
  });
})

你可能感兴趣的:(工具,pdf,opencv,javascript,python,node.js)