双十一无套路,paddlepaddle一键识别到手价

2022-01-07 08:01:49 浏览数 (1)

简介

一年一度的双十一剁手节又来了,电商玩法淘箩也越来越复杂,你还在重拾丢掉多年的数学算到手价么?尤其是电商小伙伴们,还在为了算竞对到手价头疼么?!

不用怕,paddlepaddle开源模型库教你一键识别到手价

前面写过一篇飞桨的ocr识别

《PaddleHub一键OCR中文识别(超轻量8.1M模型,火爆)——本地实现》

前两天把这个算法扩展了下,应用于淘宝商品的到手价识别

识别效果展示

部分图片及结果如下图所示,测试了120张图片,一张识别错误,一张未识别出来,主图不存在预估到手价的也准确识别并提示无目标价,总体识别准确率尚可,凑合能用。

代码&逻辑

基本逻辑:

如上图所示,需要先配置到手价文案,调用飞桨ocr识别出对应文案坐标,以正则筛选符合要求的目标文本(也可不做正则匹配,主要为了降低计算距离的复杂度),计算各文本到目标文案之间的距离,取距离目标文案最近的识别结果即可。

为了保证代码运行稳定性,本代码读取本地文件进行识别,与爬取商品主图拆分开了。很多工具可以爬取商品主图,可以先爬取下来再识别,后续有时间再分享商品主图的爬虫的代码吧。

完整代码如下:

代码语言:javascript复制
import os
import cv2
import re
import paddlehub as hub

# 完善版本2.0,速度慢,全部文本验证距离,因为有一部分目标参考位置会在下方


# 加载移动端预训练模型
ocr = hub.Module(name="chinese_ocr_db_crnn_mobile")


def get_txt(image_path):
    return ocr.recognize_text(images=[cv2.imread(image_path)])


def handle_data(txt_data):
    pass


def order_text_box_position(txt_data):
    """
    文本对位置排序,从左上到右下,并选取左下和右下的纯数字|带¥符号的|以【起】结尾的

    一般 带¥符号的|以【起】结尾的 可以确认为目标值,不过最好加一个距离验证

    坐标顺序为:左上 右上、右下、左下,图片左上角为起始原点[0,0]

    坐标值为[横坐标,纵坐标]

    """

    # 预选列,剔除其他干扰文本
    pre_select_list = []
    for j in txt_data[0]['data']:
        string = j['text'].replace(" ", "")
        if re.findall("^d .d*$|^¥d .d*$|^d .d*起$|^¥d $|^d 起$|^d $", string):
            pre_select_list.append(j)
        else:
            pass
    if len(pre_select_list) == 0:
        return "无目标价"
    else:

        # 获取参考位置坐标
        reference_position = get_reference_position(txt_data)

        # 计算距离求最小距离
        # 注意:小数点结尾,被分割了,找下一个距离最近的文本拼接,此处目标为选出来的整数项
        return cal_min_distance(reference_position,  pre_select_list)


def cal_min_distance(reference_position, inner_elements):
    """

    计算距离,取到最小距离的值,返回目标价

    reference_position:参考目标位置

    inner_elements:预选元素列表

    """
    distance_list = []
    distance_list1 = []
    x0, y0 = reference_position[0]
    for i in inner_elements:
        x1, y1 = i['text_box_position'][0]
        d = (x1 - x0) ** 2   (y1 - y0) ** 2  # 不开方也可,只比大小不取值
        distance_list.append(d)
    price = inner_elements[distance_list.index(min(distance_list))]['text'].replace(" ", "")
    if (price[-1] == ".") & (len(inner_elements) > 1):
        x0_, y0_ = inner_elements[distance_list.index(min(distance_list))]['text_box_position'][0]
        for i in inner_elements:
            x1, y1 = i['text_box_position'][0]
            if (x1 != x0) & (y1 != y0):  # 排除自己
                d = (x1 - x0) ** 2   (y1 - y0) ** 2  # 不开方也可,只比大小不取值
                distance_list1.append(d)
        decimal_price = inner_elements[distance_list1.index(min(distance_list))]['text'].replace(" ", "")
        return "".join([price, decimal_price])
    else:
        return price


def get_reference_position(txt_data):
    """获取参考位置坐标"""

    # 读取目标文本
    f = open("parameter.txt", encoding='utf8')
    reference_txt = f.readlines()
    f.close()
    # print(reference_txt)
    for i in reference_txt:
        for j in txt_data[0]['data']:
            if i.split('n')[0] in j['text']:
                return j['text_box_position']
    return "无目标位置,检查配置和图片"


def main():
    """主程序,循环图片路径"""
    dir_path = "./picture"
    pictures = os.listdir(dir_path)
    for picture in pictures:
        image_path = os.path.join(dir_path, picture)
        txt_data = get_txt(image_path)
        price = order_text_box_position(txt_data)
        print(f"商品{picture.split('.')[0]}  预估到手价:{price}")


if __name__ == '__main__':
    main()

# # cv2无法识别中文路径,使用英文路径
# image_path = "./picture/1.jpg"
# txt_data = get_txt(image_path)
# print(txt_data[0]['data'])
#
# # 获取参考位置坐标
# reference_position = get_reference_position(txt_data)
# print(reference_position)
#
# price = order_text_box_position(txt_data)
# print(f"预估到手价格:{price}")

0 人点赞