You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Python与OpenCV提取加油站价格牌的油价信息

加油站价格牌信息提取方案

针对你遇到的价格牌区域定位问题,这里提供一套基于OpenCV的完整实现方案,核心思路是先通过颜色掩码+形态学操作精准定位价格牌,再利用油品对应颜色方块区分品类,最后提取价格(可结合OCR完成数字识别)。

一、核心步骤

  1. 定位价格牌区域:通过HSV颜色空间筛选价格牌底色,结合形态学操作去除噪点,提取最大轮廓作为价格牌ROI(感兴趣区域)。
  2. 区分油品类型:提取价格左侧颜色方块的平均颜色,匹配国内标准(绿=汽油、黑=柴油、黄=LPG)。
  3. 提取与识别价格:分割价格区域,后续可接入OCR工具完成数字识别(示例中模拟输出结果)。

二、完整代码

import cv2
import numpy as np

def get_price_board_roi(src_img):
    # 转换为HSV颜色空间,更适合颜色筛选
    hsv = cv2.cvtColor(src_img, cv2.COLOR_BGR2HSV)
    # 定义价格牌底色的HSV范围(适配示例中的白色底色,可根据实际图片调整)
    lower_bound = np.array([0, 0, 200])
    upper_bound = np.array([180, 30, 255])
    mask = cv2.inRange(hsv, lower_bound, upper_bound)
    
    # 形态学闭运算:先膨胀再腐蚀,消除小噪点
    kernel = np.ones((5, 5), np.uint8)
    mask_clean = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel)
    
    # 查找轮廓并按面积排序,取最大的轮廓(即价格牌)
    contours, _ = cv2.findContours(mask_clean, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    contours_sorted = sorted(contours, key=cv2.contourArea, reverse=True)
    board_rect = cv2.boundingRect(contours_sorted[0])
    x, y, w, h = board_rect
    # 提取价格牌ROI
    return src_img[y:y+h, x:x+w]

def judge_fuel_type(color_block):
    # 计算颜色区域的平均BGR值
    avg_b, avg_g, avg_r = np.mean(color_block, axis=(0, 1))
    # 匹配国内油品颜色标准
    if avg_g > avg_r and avg_g > avg_b:
        return "95号汽油"
    elif avg_b < 50 and avg_g < 50 and avg_r < 50:
        return "柴油"
    elif avg_r > avg_g and avg_g > avg_b:
        return "液化石油气(LPG)"
    return "未知油品"

def extract_price_info(board_roi):
    # 转换为灰度图并做反向阈值处理,突出白色数字
    gray = cv2.cvtColor(board_roi, cv2.COLOR_BGR2GRAY)
    _, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY_INV)
    
    # 查找数字轮廓
    contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    # 按y坐标排序,保证从上到下处理条目
    contours_sorted = sorted(contours, key=lambda c: cv2.boundingRect(c)[1])
    
    price_results = []
    for cnt in contours_sorted:
        x, y, w, h = cv2.boundingRect(cnt)
        # 过滤小轮廓(噪点)
        if w < 20 or h < 20:
            continue
        
        # 定位价格左侧的颜色方块(根据实际布局调整偏移量)
        color_block_x = x - 50
        if color_block_x > 0:
            color_area = board_roi[y:y+h, color_block_x:color_block_x+30]
            fuel_type = judge_fuel_type(color_area)
            
            # 这里模拟OCR识别结果,实际可替换为Tesseract等工具的识别输出
            if fuel_type == "柴油":
                price = "32.20"
            elif fuel_type == "95号汽油":
                price = "32.20"
            elif fuel_type == "液化石油气(LPG)":
                price = "13.90"
            price_results.append(f"{fuel_type} - {price}")
    return price_results

# 主执行流程
if __name__ == "__main__":
    # 读取图片
    original_img = cv2.imread("media/totem1.jpeg")
    # 提取价格牌ROI
    board_roi = get_price_board_roi(original_img)
    # 获取价格信息
    price_list = extract_price_info(board_roi)
    
    # 输出结果
    print("提取到的油价信息:")
    for item in price_list:
        print(f"- {item}")
    
    # 显示处理后的价格牌(可选)
    cv2.imshow("Price Board ROI", board_roi)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

三、关键优化说明

  • HSV颜色筛选:相比RGB,HSV对光照变化的鲁棒性更强,能更精准定位价格牌底色。
  • 形态学操作:闭运算有效消除图片中的小噪点,避免误识别无关轮廓。
  • 轮廓排序:按y坐标排序保证油品条目从上到下的顺序正确,匹配价格牌的布局。
  • 颜色平均判断:取颜色方块的平均颜色而非单个像素,避免局部色差影响判断。

四、后续提升建议

  • 数字识别:建议使用pytesseract(Tesseract OCR)替代模拟输出,识别准确率更高,需提前安装Tesseract引擎和pytesseract库。
  • 自适应阈值:可改用cv2.adaptiveThreshold处理光照不均的图片,进一步提升阈值处理效果。
  • 透视矫正:如果价格牌存在倾斜,可通过透视变换矫正后再进行区域提取,优化后续识别效果。

内容的提问来源于stack exchange,提问作者opth

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 02:55:32