圖片裁剪-文字識別-文字新增

云岛夜川川發表於2024-07-23

前言

物件接到朋友的委託將幾十張截圖的鞋子圖片進行裁剪,再貼上鞋子的款式。想著這不是可以使用指令碼來完成嗎,人工多累呀。

圖片裁剪

使用 Image庫中的crop函式,傳入的引數是一個座標元組,左上角的座標和右下角的座標。(x1,y1,x2,y2),裁剪好之後使用save儲存。

def crop_img(img_path,save_name):
    img = Image.open(img_path)
    filename = img.filename[:-4]
# 獲取鞋子的位置(根據實際情況調整)
    shoes_box = (0, 400, 1080, 1250)  # 左上X,左上Y,右下X,右下Y
    shoes_img = img.crop(shoes_box)
    shoes_img.save(save_name)
    print('crop save ok')
    return save_name

文字識別

使用pytesseract來實現,使用其中的函式image_to_string()來識別。需要先安裝tesseract。安裝地址https://digi.bib.uni-mannheim.de/tesseract/?C=M;O=D

效果還不錯。

庫安裝

pip install pytesseract安裝庫,
再安裝tesseract,上面連結地址,然後安裝好後將軟體的安裝地址加入環境變數。
image
使用tesseract --version可以檢測安裝是否成功。
如果不配置環境變數就不會使用預設路徑來執行tesseract。

中文識別

使用官方預設不支援識別中文,需要下載中文包。地址https://github.com/tesseract-ocr/tessdata/tree/main 中的chi_sim.traineddata。為中文簡體包。下載下來之後放入tesseract的tessdata目錄下。
就可以使用pytesseract.image_to_string(img,lang='chi_sim')來識別中文了。

def ocr_text(img_path):
    img = Image.open(img_path).convert('L') #L表示以灰度模式開啟,可提高檢測效果

    text = pytesseract.image_to_string(img,lang='chi_sim1')
    part = r'鞋.*款'
    match_ = re.search(part, text).group()[1::].replace(' ', '')
    # print(text)
    return match_

文字新增

def cv2_img_add_text_with_bg(img_path,
                            result_img_path,
                             text: str,
                             left: int,
                             top: int,
                             textColor=(255, 0, 0),
                             textSize=20,
                             bgColor=(0, 0, 0),  # 新增:文字背景顏色,預設為黑色
                             bgPadding=(5, 5),     # 新增:文字背景邊緣 padding,預設各方向5畫素
                             filepath="D:\\app\\ocr\\tessdata\\simsun.ttc",

                             ):
    """
    在圖片上寫中文文字,並帶有指定顏色的背景
    """


    img = cv2.imread(img_path)
    if isinstance(img, np.ndarray):  # 確保是OpenCV影像格式
        img_pil = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
    else:
        raise TypeError("img must be a numpy ndarray")

    draw = ImageDraw.Draw(img_pil)
    fontStyle = ImageFont.truetype(filepath, textSize, encoding="utf-8")

    # 計算文字框的尺寸以確定背景矩形的大小
    # 使用getbbox()方法間接獲取文字尺寸,注意getbbox返回的是一個包含左上角和右下角座標的元組
    text_bbox = draw.textbbox((0, 0), text, font=fontStyle)
    textWidth = text_bbox[2] - text_bbox[0]
    textHeight = text_bbox[3] - text_bbox[1]

    # 繪製背景矩形
    bgLeft = left - bgPadding[0]
    bgTop = top - bgPadding[1]
    draw.rectangle([(bgLeft, bgTop), (bgLeft + textWidth, bgTop + textHeight)], fill=bgColor)

    # 繪製文字
    draw.text((left, top), text, textColor, font=fontStyle)

    # 轉換回OpenCV格式並返回
    img_text = cv2.cvtColor(np.array(img_pil), cv2.COLOR_RGB2BGR)

    cv2.imwrite(result_img_path,img_text)

    print('put ok')

中文字型下載http://xiazaiziti.com/category/zhongwenziti

例項程式碼和效果


import pytesseract
import re

import numpy as np
from PIL import Image, ImageDraw, ImageFont
import cv2
import os

# 讀取圖片

num = 1
def crop_img(img_path,save_name):
    img = Image.open(img_path)
    filename = img.filename[:-4]
# 獲取鞋子的位置(根據實際情況調整)
    shoes_box = (0, 400, 1080, 1250)  # 左上X,左上Y,右下X,右下Y
    shoes_img = img.crop(shoes_box)
    shoes_img.save(save_name)
    print('crop save ok')
    return save_name

img_path = "D:\\Desktop\\1.jpg"
img_crop_path = "D:\\Desktop\\1_crop.jpg"
# crop_img(img_path)
def ocr_text(img_path):
    img = Image.open(img_path).convert('L') #L表示灰度模式,可提高檢測效果

    text = pytesseract.image_to_string(img,lang='chi_sim1')
    part = r'鞋.*款'
    match_ = re.search(part, text).group()[1::].replace(' ', '')
    # print(text)
    return match_

def cv2_img_add_text_with_bg(img_path,
                            result_img_path,
                             text: str,
                             left: int,
                             top: int,
                             textColor=(255, 0, 0),
                             textSize=20,
                             bgColor=(0, 0, 0),  # 新增:文字背景顏色,預設為黑色
                             bgPadding=(5, 5),     # 新增:文字背景邊緣 padding,預設各方向5畫素
                             filepath="D:\\app\\ocr\\tessdata\\simsun.ttc",

                             ):
    """
    在圖片上寫中文文字,並帶有指定顏色的背景
    """


    img = cv2.imread(img_path)
    if isinstance(img, np.ndarray):  # 確保是OpenCV影像格式
        img_pil = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
    else:
        raise TypeError("img must be a numpy ndarray")

    draw = ImageDraw.Draw(img_pil)
    fontStyle = ImageFont.truetype(filepath, textSize, encoding="utf-8")

    # 計算文字框的尺寸以確定背景矩形的大小
    # 使用getbbox()方法間接獲取文字尺寸,注意getbbox返回的是一個包含左上角和右下角座標的元組
    text_bbox = draw.textbbox((0, 0), text, font=fontStyle)
    textWidth = text_bbox[2] - text_bbox[0]
    textHeight = text_bbox[3] - text_bbox[1]

    # 繪製背景矩形
    bgLeft = left - bgPadding[0]
    bgTop = top - bgPadding[1]
    draw.rectangle([(bgLeft, bgTop), (bgLeft + textWidth, bgTop + textHeight)], fill=bgColor)

    # 繪製文字
    draw.text((left, top), text, textColor, font=fontStyle)

    # 轉換回OpenCV格式並返回
    img_text = cv2.cvtColor(np.array(img_pil), cv2.COLOR_RGB2BGR)

    cv2.imwrite(result_img_path,img_text)

    print('put ok')


def get_file_names(directory):
    """
    返回指定目錄下所有檔案的名稱列表(不包括子目錄中的檔案)。

    :param directory: 要讀取的目錄路徑
    :return: 檔名列表
    """
    # 確保給定的路徑是絕對路徑,以避免相對路徑可能引起的錯誤
    abs_directory = os.path.abspath(directory)

    # 使用listdir()獲取目錄中的所有條目
    entries = os.listdir(abs_directory)

    # 過濾出檔案(而非子目錄)
    file_names = [entry for entry in entries if os.path.isfile(os.path.join(abs_directory, entry))]

    return file_names

if __name__ == "__main__":
    num =1
    save_directory = 'D:\\Desktop\\save\\crop\\'
    file_ = 'D:\\app\\QQ\\Filerev\\'
    filelist = get_file_names(file_)
    for file in filelist:
        file_path = file_ +file

        text = ocr_text(file_path)
        print(text)
        cro_save_file_name = save_directory + file
        crop_img(file_path,cro_save_file_name)
        result_img = 'D:\\Desktop\\save\\result\\'+file
        cv2_img_add_text_with_bg(cro_save_file_name, result_img,text, 800, 750, textColor=(255, 255, 255), textSize=70)

將下面這張圖片
image

轉成:
image

相關文章