利用yolov8零售商品识别实现的智能结算系统 yolo+后端flask+数据库sqlite+前端html(从零开始,全流程教学)

这篇具有很好参考价值的文章主要介绍了利用yolov8零售商品识别实现的智能结算系统 yolo+后端flask+数据库sqlite+前端html(从零开始,全流程教学)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

全流程教程,从数据采集到模型使用到最终展示。 支持用户点击添加至购物车、图片识别添加至购物车、摄像头识别添加至购物车,还包括用户信息,商品展示等功能。若有任何疑问和建议欢迎评论区讨论。

摄像头识别添加至购物车

利用yolov8零售商品识别实现的智能结算系统 yolo+后端flask+数据库sqlite+前端html(从零开始,全流程教学),目标检测应用,yolov8,YOLO,零售,数据库,目标检测,html5
图片识别添加至购物车
利用yolov8零售商品识别实现的智能结算系统 yolo+后端flask+数据库sqlite+前端html(从零开始,全流程教学),目标检测应用,yolov8,YOLO,零售,数据库,目标检测,html5

用户点击添加至购物车

利用yolov8零售商品识别实现的智能结算系统 yolo+后端flask+数据库sqlite+前端html(从零开始,全流程教学),目标检测应用,yolov8,YOLO,零售,数据库,目标检测,html5
先放上最终UI实现效果,UI又更新了一波。所以下面视频和新UI可能不太相同。
利用yolov8零售商品识别实现的智能结算系统 yolo+后端flask+数据库sqlite+前端html(从零开始,全流程教学),目标检测应用,yolov8,YOLO,零售,数据库,目标检测,html5

利用yolov8零售商品识别实现的智能结算系统 yolo+后端flask+数据库sqlite+前端html(从零开始,全流程教学),目标检测应用,yolov8,YOLO,零售,数据库,目标检测,html5

1. 数据集的制作

已经处理了一份数据形成了对应的数据集。 数据集包括200种常见的商品,如可乐、泡面、薯片等。有训练图片6000张,测试图片1000张。

['上好佳荷兰豆55g', '菜园小饼80g', '上好佳鲜虾片40g', '上好佳蟹味逸族40g', '妙脆角魔力炭烧味65g', '盼盼烧烤牛排味块105g', '上好佳鲜虾条40g', '上好佳洋葱圈40g', '上好佳日式鱼果海苔味50g', '奇多日式牛排味90g', '奇多美式火鸡味90g', '上好佳粟米条草莓味40g', '甘源蟹黄味瓜子仁75g', '惠宜开心果140g', '惠宜咸味花生350g', '惠宜腰果160g', '惠宜枸杞100g', '惠宜地瓜干228g', '惠宜泰国芒果干80g', '惠宜黄桃果干75g', '惠宜柠檬片65g', '新疆和田滩枣454g', '惠宜香菇100g', '惠宜桂圆干500g', '惠宜茶树菇200g', '豪雄单片黑木耳150g', '惠宜煮花生454g', '惠宜黄花菜100g', '洽洽凉茶瓜子150g', '洽洽奶香味瓜子150g', '车仔茶包绿茶50g', '车仔茶包红茶50g', '优乐美香芋味80g', '优乐美红豆奶茶65g', '欢泥冲调土豆粥25g', '江中猴姑早餐米稀40g', '永和豆浆甜豆浆粉210g', '立顿柠檬风味茶180g', '桂格多种莓果麦片40g', '荣怡谷麦加黑米味30g', '荣怡谷麦加红豆味30g', '今野香辣牛肉面112g', '今野老坛酸菜牛肉面118g', '今野红烧牛肉面114g', '合味道海鲜风味84g', '康师傅白胡椒肉骨面76g', '康师傅香辣牛肉面105g', '康师傅香辣蒜味排骨面108g', '康师傅藤椒牛肉面82g', '华丰鸡肉三鲜伊面87g', '康师傅黑胡椒牛排面104g', '五谷道场红烧牛肉面100g', '康师傅老坛酸菜牛肉面114g', 'Aji泡芙饼干芒果菠萝味60g', '庆联蓝莓味夹心饼63g', '庆联凤梨味夹心饼63g', '庆联草莓味夹心饼63g', '嘉顿威化饼干草莓味50g', '嘉顿威化饼干柠檬味50g', '爱时乐香草牛奶味50g', '爱时乐巧克力味50g', '百力滋海苔味60g', '百力滋草莓牛奶味45g', '雀巢脆脆鲨80g', '纳宝帝巧克力味威化58g', '桂力地中海风味面包条50g', '康师傅妙芙巧克力味48g', '爱乡亲唱片面包90g', '达利园派草莓味单个装*', 'mini奥利奥55g', '农夫山泉矿泉水550ml', '怡宝矿泉水555ml', '可口可乐零度500ml', '可口可乐500ml', '百事可乐600ml', '芬达苹果味500ml', '芬达橙味500ml', '雪碧500ml', '喜力啤酒500ml', '百威啤酒600ml', '百事可乐330ml', '可口可乐330ml', '王老吉310ml', '茶派柚子绿茶500ml', '茶派玫瑰荔枝红茶500ml', '康师傅冰红茶250ml', '加多宝250ml', 'RIO果酒水蜜桃味275ml', 'RIO果酒蓝玫瑰威士忌味275ml', '牛栏山二锅头100ml', '哈尔滨啤酒330ml', '青岛啤酒330ml', '雪花啤酒330ml', '哈尔滨啤酒500ml', 'KELER啤酒500ml', '百威啤酒500ml', 'QQ星全聪奶125ml', 'QQ星均膳奶125ml', '娃哈哈AD钙奶220g', '活力宝动力源105ml', '旺仔牛奶复原乳250ml', '伊利纯牛奶250ml', '维他低糖原味豆奶250ml', '百怡花生牛奶250ml', '惠宜原味豆奶250ml', '伊利优酸乳250ml', '伊利早餐奶250ml', '达利园桂圆莲子360g', '银鹭冰糖百合银耳280g', '喜多多什锦椰果567g', '都乐菠萝块567g', '都乐菠萝块234g', '银鹭薏仁红豆粥280g', '银鹭莲子玉米粥280g', '银鹭紫薯紫米粥280g', '银鹭椰奶燕麦粥280g', '银鹭黑糖桂圆280g', '梅林午餐肉340g', '珠江桥牌豆豉鱼150g', '古龙原味黄花鱼120g', '雄鸡标椰浆140ml', '德芙芒果酸奶巧克力42g', '德芙摩卡巴旦木巧克力43g', '德芙百香果白巧克力42g', 'MM花生牛奶巧克力豆40g', 'MM牛奶巧克力豆40g', '好时牛奶巧克力40g', '好时曲奇奶香白巧克力40g', '脆香米海苔白巧克力24g', '脆香米奶香白巧克力24g', '士力架花生夹心巧克力51g', '士力架燕麦花生夹心巧克力40g', '士力架辣花生夹心巧克力40g', '炫迈果味浪薄荷味37g', '炫迈果味浪柠檬味37g', '炫迈薄荷味21g', '炫迈葡萄味21g', '炫迈西瓜味21g', '炫迈葡萄味50g', '绿箭无糖薄荷糖茉莉花茶味34g', '绿箭5片装15g', '比巴卜棉花泡泡糖可乐味11g', '比巴卜棉花泡泡堂葡萄味11g', '星爆缤纷原果味25g', '阿尔卑斯焦香牛奶味硬糖45g', '阿尔卑斯牛奶软糖黄桃酸奶味47g', '阿尔卑斯牛奶软糖蓝莓酸奶味47g', '王老吉润喉糖28g', '伊利牛奶片蓝莓味32g', '熊博士口嚼糖草莓牛奶味52g', '彩虹糖原果味45g', '宝鼎天鱼陈酿米醋245ml', '恒顺香醋340ml', '太太乐鸡精200g', '家乐香菇鸡茸汤料41g', '惠宜辣椒粉15g', '惠宜生姜粉15g', '味好美椒盐20g', '海星加碘精制盐400g', '恒顺料酒500ml', '东古味极鲜酱油150ml', '东古一品鲜酱油150ml', '欣和六月鲜酱油160ml', '李施德林零度漱口水80ml', '舒肤佳纯白清香沐浴露100ml', '美涛定型啫喱水60ml', '清扬男士洗发露活力运动薄荷型50ml', '蓝月亮风清白兰洗衣液80g', '高露洁亮白小苏打180g', '高露洁冰爽180g', '舒亮皓齿白80g', '云南白药牙膏45g', '舒克宝贝儿童牙刷', '清风原木纯品金装100x3', '洁柔face150x3', '斑布100x3', '维达婴儿150x3', '相印小黄人150x3', '清风原木纯品黑耀150x3', '洁云绒触感130x3', '舒洁萌印花120x2', '相印红悦130x3', '得宝苹果木味90x4', '清风新韧纯品130x3', '金鱼竹浆绿135x3', '清风原木纯品150x2', '洁柔face130x3', '维达立体美110x3', '洁柔CS单包*', '相印小黄人单包*', '清风原色单包*', '相印茶语单包*', '清风质感纯品单包*', '米奇1928笔记本', '广博固体胶15g', '票据文件袋', '晨光蜗牛改正带', '鸿泰液体胶50g', '马培德自粘性标签', '东亚记号笔']

利用yolov8零售商品识别实现的智能结算系统 yolo+后端flask+数据库sqlite+前端html(从零开始,全流程教学),目标检测应用,yolov8,YOLO,零售,数据库,目标检测,html5

利用yolov8零售商品识别实现的智能结算系统 yolo+后端flask+数据库sqlite+前端html(从零开始,全流程教学),目标检测应用,yolov8,YOLO,零售,数据库,目标检测,html5

自己制作数据集可以参考如下步骤

1.1 使用爬虫采集数据集

可以通过爬虫爬取商品的图片。
这里直接上代码,如果想详细了解可以参考我的另外一篇文章python爬取百度图片,可以大量批量爬取(仅供学习,很详细)

import requests#导入请求库
import time
import re
#设定爬取的总数
total=90
batch_size=30
all_success=0
for i in range(total//batch_size):
    url='https://image.baidu.com/search/acjson?tn=resultjson_com&logid=10371129381236677678&ipn=rj&ct=201326592&is=&fp=result&fr=&word=可乐&queryWord=可乐&cl=2&lm=-1&ie=utf-8&oe=utf-8&adpicid=&st=&z=&ic=&hd=&latest=&copyright=&s=&se=&tab=&width=&height=&face=&istype=&qc=&nc=1&expermode=&nojc=&isAsync=&pn={0}&rn=30&gsm=3c&1682846532783='.format((i+1)*30)
 
    headers={'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.63 Safari/537.36'}
    res=requests.get(url,headers=headers)#发送请求,返回数据
    html=res.text#把返回的内容解析
    # 使用正则表达式匹配图片url
    img_url_list=re.findall('"thumbURL":"(.*?)"',html)
    #print(img_url_list)
    for j in range(len(img_url_list)):
        res_img=requests.get(img_url_list[j],headers=headers)
        img=res_img.content#这个里是图片,我们需要返回二进制数据
        # 图片保存的路径
        with open('D:\\code\\person\\mask\\'+str(all_success)+'mask_img.jpg','wb')as f:
            f.write(img)
        time.sleep(3)#每当保存一张图片,先暂停一下,不然太频繁容易发现是机器爬虫,导致无法获取
        all_success=all_success+1
        print("爬取{}张图片成功".format(all_success))
print("爬取{}张图片成功".format(all_success))

1.2 使用labelme对图片进行标注

labelme是图形图像注释工具,它是用Python编写的,并将Qt用于其图形界面。说直白点,它是有界面的, 像软件一样,可以交互,但是它又是由命令行启动的,比软件的使用稍微麻烦点。其界面如下图:

利用yolov8零售商品识别实现的智能结算系统 yolo+后端flask+数据库sqlite+前端html(从零开始,全流程教学),目标检测应用,yolov8,YOLO,零售,数据库,目标检测,html5
github链接: labelme https://github.com/wkentaro/labelme
它的功能很多,包括:

  • 对图像进行多边形,矩形,圆形,多段线,线段,点形式的标注(可用于目标检-测,图像分割等任务)。
  • 对图像进行进行 flag形式的标注(可用于图像分类 和 清理 任务)。
  • 视频标注 - 生成 VOC 格式的数据集(for semantic / instancesegmentation)
  • 生成 COCO 格式的数据集(for instance segmentation)

2. YOLOv8

2.1YOLO算法简单介绍

YOLO框架(You Only Look Once)与RCNN系列算法不一样,是以不同的方式处理对象检测。它将整个图像放在一个实例中,并预测这些框的边界框坐标和及所属类别概率。使用YOLO算法最大优的点是速度极快,每秒可处理45帧,也能够理解一般的对象表示。

在本节中,将介绍YOLO用于检测给定图像中的对象的处理步骤。

首先,输入图像:
利用yolov8零售商品识别实现的智能结算系统 yolo+后端flask+数据库sqlite+前端html(从零开始,全流程教学),目标检测应用,yolov8,YOLO,零售,数据库,目标检测,html5

然后,YOLO将输入图像划分为网格形式(例如3 X 3):
利用yolov8零售商品识别实现的智能结算系统 yolo+后端flask+数据库sqlite+前端html(从零开始,全流程教学),目标检测应用,yolov8,YOLO,零售,数据库,目标检测,html5

最后,对每个网格应用图像分类和定位处理,获得预测对象的边界框及其对应的类概率。
整个过程是不是很清晰,下面逐一详细介绍。首先需要将标记数据传递给模型以进行训练。假设已将图像划分为大小为3 X 3的网格,且总共只有3个类别,分别是行人(c1)、汽车(c2)和摩托车(c3)。因此,对于每个单元格,标签y将是一个八维向量:

利用yolov8零售商品识别实现的智能结算系统 yolo+后端flask+数据库sqlite+前端html(从零开始,全流程教学),目标检测应用,yolov8,YOLO,零售,数据库,目标检测,html5

其中:
pc定义对象是否存在于网格中(存在的概率);
bx、by、bh、bw指定边界框;
c1、c2、c3代表类别。如果检测对象是汽车,则c2位置处的值将为1,c1和c3处的值将为0;
假设从上面的例子中选择第一个网格:

利用yolov8零售商品识别实现的智能结算系统 yolo+后端flask+数据库sqlite+前端html(从零开始,全流程教学),目标检测应用,yolov8,YOLO,零售,数据库,目标检测,html5

由于此网格中没有对象,因此pc将为零,此网格的y标签将为:
利用yolov8零售商品识别实现的智能结算系统 yolo+后端flask+数据库sqlite+前端html(从零开始,全流程教学),目标检测应用,yolov8,YOLO,零售,数据库,目标检测,html5

?意味着其它值是什么并不重要,因为网格中没有对象。下面举例另一个有车的网格(c2=1):
利用yolov8零售商品识别实现的智能结算系统 yolo+后端flask+数据库sqlite+前端html(从零开始,全流程教学),目标检测应用,yolov8,YOLO,零售,数据库,目标检测,html5

在为此网格编写y标签之前,首先要了解YOLO如何确定网格中是否存在实际对象。大图中有两个物体(两辆车),因此YOLO将取这两个物体的中心点,物体将被分配到包含这些物体中心的网格中。中心点左侧网格的y标签会是这样的:
利用yolov8零售商品识别实现的智能结算系统 yolo+后端flask+数据库sqlite+前端html(从零开始,全流程教学),目标检测应用,yolov8,YOLO,零售,数据库,目标检测,html5

由于此网格中存在对象,因此pc将等于1,bx、by、bh、bw将相对于正在处理的特定网格单元计算。由于检测出的对象是汽车,所以c2=1,c1和c3均为0。对于9个网格中的每一个单元格,都具有八维输出向量。最终的输出形状为3X3X8。
使用上面的例子(输入图像:100X100X3,输出:3X3X8),模型将按如下方式进行训练:
利用yolov8零售商品识别实现的智能结算系统 yolo+后端flask+数据库sqlite+前端html(从零开始,全流程教学),目标检测应用,yolov8,YOLO,零售,数据库,目标检测,html5

使用经典的CNN网络构建模型,并进行模型训练。在测试阶段,将图像传递给模型,经过一次前向传播就得到输出y。为了简单起见,使用3X3网格解释这一点,但通常在实际场景中会采用更大的网格(比如19X19)。

即使一个对象跨越多个网格,它也只会被分配到其中点所在的单个网格。可以通过增加更多网格来减少多个对象出现在同一网格单元中的几率。

2.2 YOLOv8获取与调试

2.2.1 通过pip的方式安装yolov8
pip install ultralytics
2.2.2 安装yolov8训练所需的第三方库:
  1. 检查是否正确安装好anaconda。
    windows+r打开cmd,输入 conda -V。若出现版本号,则安装成功。
    利用yolov8零售商品识别实现的智能结算系统 yolo+后端flask+数据库sqlite+前端html(从零开始,全流程教学),目标检测应用,yolov8,YOLO,零售,数据库,目标检测,html5
  2. 检查是否正确安装好pytorch
import torch
if __name__ == '__main__':
     print(torch.zeros(1))

利用yolov8零售商品识别实现的智能结算系统 yolo+后端flask+数据库sqlite+前端html(从零开始,全流程教学),目标检测应用,yolov8,YOLO,零售,数据库,目标检测,html5

2.2.3 配置自己的yaml文件

配置描述数据集位置的shop200.yaml 。这里train指定训练数据集所在位置,val测试数据集所在位置,nc类别数,names类别的名称

# YOLOv5 🚀 by Ultralytics, GPL-3.0 license
# COCO128 dataset https://www.kaggle.com/ultralytics/coco128 (first 128 images from COCO train2017)
# Example usage: python train.py --data coco128.yaml
# parent
# ├── yolov5
# └── datasets
#     └── coco128  ← downloads here


# Train/val/test sets as 1) dir: path/to/imgs, 2) file: path/to/imgs.txt, or 3) list: [path/to/imgs1, path/to/imgs2, ..]
path: D:/dataset/shop200  # dataset root dir
train: images/val2019  # train images (relative to 'path') 128 images
val: images/test2019  # val images (relative to 'path') 128 images
test:  # test images (optional)

# Classes
nc: 200  # number of classes
names: ['1_puffed_food', '2_puffed_food', '3_puffed_food', '4_puffed_food', '5_puffed_food', '6_puffed_food', '7_puffed_food', '8_puffed_food', '9_puffed_food', '10_puffed_food', '11_puffed_food', '12_puffed_food', '13_dried_fruit', '14_dried_fruit', '15_dried_fruit', '16_dried_fruit', '17_dried_fruit', '18_dried_fruit', '19_dried_fruit', '20_dried_fruit', '21_dried_fruit', '22_dried_food', '23_dried_food', '24_dried_food', '25_dried_food', '26_dried_food', '27_dried_food', '28_dried_food', '29_dried_food', '30_dried_food', '31_instant_drink', '32_instant_drink', '33_instant_drink', '34_instant_drink', '35_instant_drink', '36_instant_drink', '37_instant_drink', '38_instant_drink', '39_instant_drink', '40_instant_drink', '41_instant_drink', '42_instant_noodles', '43_instant_noodles', '44_instant_noodles', '45_instant_noodles', '46_instant_noodles', '47_instant_noodles', '48_instant_noodles', '49_instant_noodles', '50_instant_noodles', '51_instant_noodles', '52_instant_noodles', '53_instant_noodles', '54_dessert', '55_dessert', '56_dessert', '57_dessert', '58_dessert', '59_dessert', '60_dessert', '61_dessert', '62_dessert', '63_dessert', '64_dessert', '65_dessert', '66_dessert', '67_dessert', '68_dessert', '69_dessert', '70_dessert', '71_drink', '72_drink', '73_drink', '74_drink', '75_drink', '76_drink', '77_drink', '78_drink', '79_alcohol', '80_alcohol', '81_drink', '82_drink', '83_drink', '84_drink', '85_drink', '86_drink', '87_drink', '88_alcohol', '89_alcohol', '90_alcohol', '91_alcohol', '92_alcohol', '93_alcohol', '94_alcohol', '95_alcohol', '96_alcohol', '97_milk', '98_milk', '99_milk', '100_milk', '101_milk', '102_milk', '103_milk', '104_milk', '105_milk', '106_milk', '107_milk', '108_canned_food', '109_canned_food', '110_canned_food', '111_canned_food', '112_canned_food', '113_canned_food', '114_canned_food', '115_canned_food', '116_canned_food', '117_canned_food', '118_canned_food', '119_canned_food', '120_canned_food', '121_canned_food', '122_chocolate', '123_chocolate', '124_chocolate', '125_chocolate', '126_chocolate', '127_chocolate', '128_chocolate', '129_chocolate', '130_chocolate', '131_chocolate', '132_chocolate', '133_chocolate', '134_gum', '135_gum', '136_gum', '137_gum', '138_gum', '139_gum', '140_gum', '141_gum', '142_candy', '143_candy', '144_candy', '145_candy', '146_candy', '147_candy', '148_candy', '149_candy', '150_candy', '151_candy', '152_seasoner', '153_seasoner', '154_seasoner', '155_seasoner', '156_seasoner', '157_seasoner', '158_seasoner', '159_seasoner', '160_seasoner', '161_seasoner', '162_seasoner', '163_seasoner', '164_personal_hygiene', '165_personal_hygiene', '166_personal_hygiene', '167_personal_hygiene', '168_personal_hygiene', '169_personal_hygiene', '170_personal_hygiene', '171_personal_hygiene', '172_personal_hygiene', '173_personal_hygiene', '174_tissue', '175_tissue', '176_tissue', '177_tissue', '178_tissue', '179_tissue', '180_tissue', '181_tissue', '182_tissue', '183_tissue', '184_tissue', '185_tissue', '186_tissue', '187_tissue', '188_tissue', '189_tissue', '190_tissue', '191_tissue', '192_tissue', '193_tissue', '194_stationery', '195_stationery', '196_stationery', '197_stationery', '198_stationery', '199_stationery', '200_stationery']
 # class names

利用yolov8零售商品识别实现的智能结算系统 yolo+后端flask+数据库sqlite+前端html(从零开始,全流程教学),目标检测应用,yolov8,YOLO,零售,数据库,目标检测,html5
yaml文件中指定是images的位置,yolo会自动寻找同级目录下labels文件夹中的同名标签,我们需要在labels文件夹中准备好标签文件。

利用yolov8零售商品识别实现的智能结算系统 yolo+后端flask+数据库sqlite+前端html(从零开始,全流程教学),目标检测应用,yolov8,YOLO,零售,数据库,目标检测,html5
利用yolov8零售商品识别实现的智能结算系统 yolo+后端flask+数据库sqlite+前端html(从零开始,全流程教学),目标检测应用,yolov8,YOLO,零售,数据库,目标检测,html5

2.2.4 开始训练
python3 train.py 

利用yolov8零售商品识别实现的智能结算系统 yolo+后端flask+数据库sqlite+前端html(从零开始,全流程教学),目标检测应用,yolov8,YOLO,零售,数据库,目标检测,html5
如果出现显卡空间不足的情况可以改小–bath参数
利用yolov8零售商品识别实现的智能结算系统 yolo+后端flask+数据库sqlite+前端html(从零开始,全流程教学),目标检测应用,yolov8,YOLO,零售,数据库,目标检测,html5

会在/runs/train/exp/weights/best.pt下生成最终的权重文件。
利用yolov8零售商品识别实现的智能结算系统 yolo+后端flask+数据库sqlite+前端html(从零开始,全流程教学),目标检测应用,yolov8,YOLO,零售,数据库,目标检测,html5

2.2.5 预测
from ultralytics import YOLO
import cv2
model = YOLO("yolov8n.pt")  # load a pretrained model (recommended for training)
res = model("https://ultralytics.com/images/bus.jpg")  # predict on an image
res_plotted = res[0].plot()
cv2.imshow("result", res_plotted)
cv2.waitKey(-1)

利用yolov8零售商品识别实现的智能结算系统 yolo+后端flask+数据库sqlite+前端html(从零开始,全流程教学),目标检测应用,yolov8,YOLO,零售,数据库,目标检测,html5

3. Flask

我们通过flask作为Web框架,Flask相对于Django而言是轻量级的Web框架。和Django不同,Flask轻巧、简洁,通过定制第三方扩展来实现具体功能。

pip3 install Flask

另外,如果你的网络访问外网不是很好的话建议使用豆瓣的镜像下载,不然会很很慢或者直接安装失败。

pip3 install Flask -i https://pypi.douban.com/simple

4. OpenCV

OpenCV(开源的计算机视觉库)是基于BSD协议,因此它可免费用于学术和商业用途。其提供C++,C,Python和Java接口,支持Windows,Linux,Mac OS,iOS和Android。

我们使用OpenCV来处理图片和视频,以便于将图片转为Yolov5模型需要的输入。

安装

首先我们得先安装另一个第三方库numpy,这是opencv的依赖库,没有它无法进行python-opencv开发。

#安装numpy:
pip install numpy
#安装opencv-python: 
pip install opencv-python

5. 数据库

数据库主要使用了python自带的sqlite数据库,但对于其他数据库如mysql等也是同理。数据库主要包含四张表。用户表users,商品种类表categories,商品表products,购物车表kart

--
-- SQLiteStudio v3.4.4 生成的文件,周六 6月 3 22:56:40 2023
--
-- 所用的文本编码:System
--
PRAGMA foreign_keys = off;
BEGIN TRANSACTION;

-- 表:categories
CREATE TABLE IF NOT EXISTS categories
		(categoryId INTEGER PRIMARY KEY,
		name TEXT
		);

-- 表:kart
CREATE TABLE IF NOT EXISTS kart (userId INTEGER, productId INTEGER, id INTEGER PRIMARY KEY AUTOINCREMENT, FOREIGN KEY (userId) REFERENCES users (userId), FOREIGN KEY (productId) REFERENCES products (productId));

-- 表:products
CREATE TABLE IF NOT EXISTS products (productId INTEGER PRIMARY KEY, name TEXT, price REAL, description TEXT, image TEXT, stock INTEGER, categoryId INTEGER, chineseName TEXT, FOREIGN KEY (categoryId) REFERENCES categories (categoryId));

-- 表:users
CREATE TABLE IF NOT EXISTS users 
		(userId INTEGER PRIMARY KEY, 
		password TEXT,
		email TEXT,
		firstName TEXT,
		lastName TEXT,
		address1 TEXT,
		address2 TEXT,
		zipcode TEXT,
		city TEXT,
		state TEXT,
		country TEXT, 
		phone TEXT
		);

COMMIT TRANSACTION;
PRAGMA foreign_keys = on;

6. 摄像头识别添加至购物车

6.1 前端

通过 io() 函数创建了一个WebSocket连接,并在点击开始检测按钮时向后端发送 start_detection 事件。在接收到图像帧数据时,将其转换为图像展示在 videoStream 元素上。如果接收到检测成功的结果,将通过 JavaScript 跳转到购物车界面。

<h1>实时检测</h1>

    <img id="videoStream" src={{ url_for('static', filename='images/wait.jpg') }} width="640" height="640">
    <br><br>
    <button id="startDetection">开始检测</button>
    <script>
      var socket = io();

      // 获取图像流的元素
      var videoStream = document.getElementById('videoStream');
      // 获取开始检测按钮的元素
      var startButton = document.getElementById('startDetection');

      // 添加点击事件监听器
      startButton.addEventListener('click', function() {
        // 向后端发送开始检测事件
        socket.emit('start_detection');
      });

      // 处理图像流
      socket.on('video_frame', function(frameBytes) {
        // 将图像流数据转换为图片展示
        var frameBlob = new Blob([frameBytes], { type: 'image/jpeg' });
        var imageUrl = URL.createObjectURL(frameBlob);
        videoStream.src = imageUrl;
      });

      // 处理检测结果
      socket.on('detection_result', function(result) {
        if (result === 'success') {
          // 跳转到购物车界面
          window.location.href = '/cart';
        }
      });

    </script>

6.2 后端

使用了Flask-SocketIO来实现WebSocket通信。当前端端发送 start_detection 事件时,后端将初始化摄像头,并在后台启动一个线程来执行检测逻辑。在检测过程中,每获取到一帧图像,后端将通过WebSocket发送给客户端。如果检测成功,后端将发送 detection_result 事件,并携带成功标识。

from flask import *
import sqlite3, hashlib, os
from flask import Flask, render_template, session
from flask_socketio import SocketIO, emit
# 摄像头参数
camera = None
detecting = False
import cv2
from PIL import Image
import numpy as np
app = Flask(__name__)
app.secret_key = 'random string'
socketio = SocketIO(app)
from ultralytics import YOLO
import cv2
model = YOLO("../best.pt")
def detect(email):
    global camera, detecting
    pre_name_list = []
    while detecting:
        socketio.sleep(0.01)
        if camera is not None:
            success, frame = camera.read()  # 读取摄像头帧
            # 如果检测到满足条件的商品,则跳出循环
            name_list=[]

            res = model.predict(frame, save=False, imgsz=640, conf=0.7)
            id_list = res[0].boxes.cls.cpu().numpy()
            namesMap = res[0].names
            detectimg=res[0].plot()
            for i in id_list:
                name_list.append(namesMap[i])
            flag=len(name_list)!=0 and len(name_list)==len(pre_name_list)
            for i,j in zip(name_list,pre_name_list):
                if i==j:
                    continue
                else:
                    flag=False
                    break
            print(pre_name_list, name_list)
            pre_name_list=name_list
            if flag :
                with sqlite3.connect('database.db') as conn:
                    cur = conn.cursor()
                    cur.execute("SELECT userId FROM users WHERE email = ?", (email,))
                    userId = cur.fetchone()[0]
                    product_id_name = {}
                    cur.execute("SELECT productId,name FROM products ")
                    res = cur.fetchall()
                    for productId, name in res:
                        product_id_name.update({name: productId})
                    productIds = []
                    for name in name_list:
                        productIds.append(product_id_name[name])
                    try:
                        for productId in productIds:
                            cur.execute("INSERT INTO kart (userId, productId) VALUES (?, ?)", (userId, productId))
                            conn.commit()
                            msg = "Added successfully"
                    except:
                        conn.rollback()
                        msg = "Error occured"
                conn.close()
                detection_successful=True
            else:
                detection_successful = False
            # 将检测结果发送到客户端
            # print("detectimg",detectimg)
            # print("frame",frame)
            ret, buffer = cv2.imencode('.jpg', detectimg )
            frame_bytes = buffer.tobytes()
            socketio.emit('video_frame', frame_bytes)
            # time.sleep(1)
            if detection_successful:
                socketio.sleep(2)
                detecting = False
                socketio.emit('detection_result', 'success')  # 发送检测结果
@socketio.on('start_detection')
def start_detection():
    global camera, detecting

    if not detecting:
        # 初始化摄像头
        email=session['email']
        camera = cv2.VideoCapture(0)  # 这里的0表示默认摄像头设备
        detecting = True

        # 启动检测
        socketio.start_background_task(target=detect,email=email)

@socketio.on('disconnect')
def disconnect():
    global camera, detecting

    if detecting:
        # 停止检测
        detecting = False
        camera.release()

7.图片识别添加至购物车

7.1前端

<h1>智能识别</h1>
    <form action="yoloPic" method="POST" enctype="multipart/form-data">
        <input type="file" name="image" accept="image/*" value="选择图片">
        <br><br>
        <input type="submit" value="识别">
    </form>

7.2后端

主要是将前端选择的图片进行读取,然后调用yolo进行检测,拿到检测结果id_list,这个主要是yolo使用的类别名,需要将其转化为product表 商品类别productId,插入到购物车表kart,然后跳转到购物车界面即可。文章来源地址https://www.toymoban.com/news/detail-691205.html

@app.route("/yoloPic", methods=['POST'])
def yoloPic():
    if 'email' not in session:
        return redirect(url_for('loginForm'))
    else:
        if 'image' not in request.files:
            return 'No file uploaded', 400

        image_file = request.files['image']
        if image_file.filename == '':
            return 'No file selected', 400
        name_list = []
        image = Image.open(image_file)
        np_array = np.array(image)

        # 将NumPy数组转换为OpenCV图像
        img = cv2.cvtColor(np_array, cv2.COLOR_RGB2BGR)
        # img = cv2.imread(image_file)
        # name_list = model.detect(name_list, img)

        res=model.predict(img, save=False, imgsz=640, conf=0.5)
        id_list = res[0].boxes.cls.cpu().numpy()
        namesMap = res[0].names
        for i in id_list:
            name_list.append(namesMap[i])
        # print(name_list)

        with sqlite3.connect('database.db') as conn:
            cur = conn.cursor()
            cur.execute("SELECT userId FROM users WHERE email = ?", (session['email'], ))
            userId = cur.fetchone()[0]
            product_id_name = {}
            cur.execute("SELECT productId,name FROM products ")
            res = cur.fetchall()
            for productId, name in res:
                product_id_name.update({name: productId})
            productIds = []
            for name in name_list:
                productIds.append(product_id_name[name])
            try:
                for productId in productIds:
                    cur.execute("INSERT INTO kart (userId, productId) VALUES (?, ?)", (userId, productId))
                    conn.commit()
                    msg = "Added successfully"
            except:
                conn.rollback()
                msg = "Error occured"
        conn.close()
        return redirect(url_for('cart'))

8.用户点击添加至购物车

@app.route("/addToCart")
def addToCart():
    if 'email' not in session:
        return redirect(url_for('loginForm'))
    else:
        productId = int(request.args.get('productId'))
        with sqlite3.connect('database.db') as conn:
            cur = conn.cursor()
            cur.execute("SELECT userId FROM users WHERE email = ?", (session['email'], ))
            userId = cur.fetchone()[0]
            try:
                cur.execute("INSERT INTO kart (userId, productId) VALUES (?, ?)", (userId, productId))
                conn.commit()
                msg = "Added successfully"
            except:
                conn.rollback()
                msg = "Error occured"
        conn.close()
        return redirect(url_for('root'))

9.用户注册登录,用户个人信息修改

def getLoginDetails():
    with sqlite3.connect('database.db') as conn:
        cur = conn.cursor()
        if 'email' not in session:
            loggedIn = False
            firstName = ''
            noOfItems = 0
        else:
            loggedIn = True
            cur.execute("SELECT userId, firstName FROM users WHERE email = ?", (session['email'], ))
            userId, firstName = cur.fetchone()
            cur.execute("SELECT count(productId) FROM kart WHERE userId = ?", (userId, ))
            noOfItems = cur.fetchone()[0]
    conn.close()
    return (loggedIn, firstName, noOfItems)


@app.route("/account/profile")
def profileHome():
    if 'email' not in session:
        return redirect(url_for('root'))
    loggedIn, firstName, noOfItems = getLoginDetails()
    return render_template("profileHome.html", loggedIn=loggedIn, firstName=firstName, noOfItems=noOfItems)

@app.route("/account/profile/edit")
def editProfile():
    if 'email' not in session:
        return redirect(url_for('root'))
    loggedIn, firstName, noOfItems = getLoginDetails()
    with sqlite3.connect('database.db') as conn:
        cur = conn.cursor()
        cur.execute("SELECT userId, email, firstName, lastName, address1, address2, zipcode, city, state, country, phone FROM users WHERE email = ?", (session['email'], ))
        profileData = cur.fetchone()
    conn.close()
    return render_template("editProfile.html", profileData=profileData, loggedIn=loggedIn, firstName=firstName, noOfItems=noOfItems)

@app.route("/account/profile/changePassword", methods=["GET", "POST"])
def changePassword():
    if 'email' not in session:
        return redirect(url_for('loginForm'))
    if request.method == "POST":
        oldPassword = request.form['oldpassword']
        oldPassword = hashlib.md5(oldPassword.encode()).hexdigest()
        newPassword = request.form['newpassword']
        newPassword = hashlib.md5(newPassword.encode()).hexdigest()
        with sqlite3.connect('database.db') as conn:
            cur = conn.cursor()
            cur.execute("SELECT userId, password FROM users WHERE email = ?", (session['email'], ))
            userId, password = cur.fetchone()
            if (password == oldPassword):
                try:
                    cur.execute("UPDATE users SET password = ? WHERE userId = ?", (newPassword, userId))
                    conn.commit()
                    msg="Changed successfully"
                except:
                    conn.rollback()
                    msg = "Failed"
                return render_template("changePassword.html", msg=msg)
            else:
                msg = "Wrong password"
        conn.close()
        return render_template("changePassword.html", msg=msg)
    else:
        return render_template("changePassword.html")

@app.route("/updateProfile", methods=["GET", "POST"])
def updateProfile():
    if request.method == 'POST':
        email = request.form['email']
        firstName = request.form['firstName']
        lastName = request.form['lastName']
        address1 = request.form['address1']
        address2 = request.form['address2']
        zipcode = request.form['zipcode']
        city = request.form['city']
        state = request.form['state']
        country = request.form['country']
        phone = request.form['phone']
        with sqlite3.connect('database.db') as con:
                try:
                    cur = con.cursor()
                    cur.execute('UPDATE users SET firstName = ?, lastName = ?, address1 = ?, address2 = ?, zipcode = ?, city = ?, state = ?, country = ?, phone = ? WHERE email = ?', (firstName, lastName, address1, address2, zipcode, city, state, country, phone, email))

                    con.commit()
                    msg = "Saved Successfully"
                except:
                    con.rollback()
                    msg = "Error occured"
        con.close()
        return redirect(url_for('editProfile'))

@app.route("/loginForm")
def loginForm():
    if 'email' in session:
        return redirect(url_for('root'))
    else:
        return render_template('login.html', error='')

@app.route("/login", methods = ['POST', 'GET'])
def login():
    if request.method == 'POST':
        email = request.form['email']
        password = request.form['password']
        if is_valid(email, password):
            session['email'] = email
            return redirect(url_for('root'))
        else:
            error = 'Invalid UserId / Password'
            return render_template('login.html', error=error)
@app.route("/logout")
def logout():
    session.pop('email', None)
    return redirect(url_for('root'))

def is_valid(email, password):
    con = sqlite3.connect('database.db')
    cur = con.cursor()
    cur.execute('SELECT email, password FROM users')
    data = cur.fetchall()
    for row in data:
        if row[0] == email and row[1] == hashlib.md5(password.encode()).hexdigest():
            return True
    return False

@app.route("/register", methods = ['GET', 'POST'])
def register():
    if request.method == 'POST':
        #Parse form data    
        password = request.form['password']
        email = request.form['email']
        firstName = request.form['firstName']
        lastName = request.form['lastName']
        address1 = request.form['address1']
        address2 = request.form['address2']
        zipcode = request.form['zipcode']
        city = request.form['city']
        state = request.form['state']
        country = request.form['country']
        phone = request.form['phone']

        with sqlite3.connect('database.db') as con:
            try:
                cur = con.cursor()
                cur.execute('INSERT INTO users (password, email, firstName, lastName, address1, address2, zipcode, city, state, country, phone) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)', (hashlib.md5(password.encode()).hexdigest(), email, firstName, lastName, address1, address2, zipcode, city, state, country, phone))

                con.commit()

                msg = "Registered Successfully"
            except:
                con.rollback()
                msg = "Error occured"
        con.close()
        return render_template("login.html", error=msg)

@app.route("/registerationForm")
def registrationForm():
    return render_template("register.html")

def allowed_file(filename):
    return '.' in filename and \
            filename.rsplit('.', 1)[1] in ALLOWED_EXTENSIONS

def parse(data):
    ans = []
    i = 0
    while i < len(data):
        curr = []
        for j in range(7):
            if i >= len(data):
                break
            curr.append(data[i])
            i += 1
        ans.append(curr)
    return ans

10.商品展示

@app.route("/")
def root():
    loggedIn, firstName, noOfItems = getLoginDetails()
    with sqlite3.connect('database.db') as conn:
        cur = conn.cursor()
        cur.execute('SELECT productId, name,chineseName, price, description, image, stock FROM products')
        itemData = cur.fetchall()
        cur.execute('SELECT categoryId, name FROM categories')
        categoryData = cur.fetchall()
    itemData = parse(itemData)   
    return render_template('home.html', itemData=itemData, loggedIn=loggedIn, firstName=firstName, noOfItems=noOfItems, categoryData=categoryData)

11.商品分类展示

@app.route("/displayCategory")
def displayCategory():
        loggedIn, firstName, noOfItems = getLoginDetails()
        categoryId = request.args.get("categoryId")
        with sqlite3.connect('database.db') as conn:
            cur = conn.cursor()
            cur.execute("SELECT products.productId, products.name,products.chineseName, products.price, products.image, categories.name FROM products, categories WHERE products.categoryId = categories.categoryId AND categories.categoryId = ?", (categoryId, ))
            data = cur.fetchall()
        conn.close()
        categoryName = data[0][5]
        data = parse(data)
        return render_template('displayCategory.html', data=data, loggedIn=loggedIn, firstName=firstName, noOfItems=noOfItems, categoryName=categoryName)

12.商品详情展示

@app.route("/productDescription")
def productDescription():
    loggedIn, firstName, noOfItems = getLoginDetails()
    productId = request.args.get('productId')
    with sqlite3.connect('database.db') as conn:
        cur = conn.cursor()
        cur.execute('SELECT productId, name, price, description, image, stock FROM products WHERE productId = ?', (productId, ))
        productData = cur.fetchone()
    conn.close()
    return render_template("productDescription.html", data=productData, loggedIn = loggedIn, firstName = firstName, noOfItems = noOfItems)

13.购物车商品展示和购物车内商品移除

from decimal import Decimal,ROUND_HALF_UP
def round_dec(n, d):
    s = '0.' + '0' * d
    return Decimal(n).quantize(Decimal(s), ROUND_HALF_UP)
@app.route("/cart")
def cart():
    if 'email' not in session:
        return redirect(url_for('loginForm'))
    loggedIn, firstName, noOfItems = getLoginDetails()
    email = session['email']
    with sqlite3.connect('database.db') as conn:
        cur = conn.cursor()
        cur.execute("SELECT userId FROM users WHERE email = ?", (email, ))
        userId = cur.fetchone()[0]
        cur.execute("SELECT kart.id, products.chineseName, products.price, products.image FROM products, kart WHERE products.productId = kart.productId AND kart.userId = ?", (userId, ))
        products = cur.fetchall()
    totalPrice = Decimal(0)
    for row in products:
        totalPrice += Decimal(row[2])
    totalPrice=round_dec(totalPrice,2)
    return render_template("cart.html", products = products, totalPrice=totalPrice, loggedIn=loggedIn, firstName=firstName, noOfItems=noOfItems)
@app.route("/removeFromCart")
def removeFromCart():
    if 'email' not in session:
        return redirect(url_for('loginForm'))
    email = session['email']
    id = int(request.args.get('id'))
    with sqlite3.connect('database.db') as conn:
        cur = conn.cursor()
        cur.execute("SELECT userId FROM users WHERE email = ?", (email, ))
        userId = cur.fetchone()[0]
        try:
            cur.execute("DELETE FROM kart WHERE id= ?", (id,))
            conn.commit()
            msg = "removed successfully"
        except:
            conn.rollback()
            msg = "error occured"
    conn.close()
    return redirect(url_for('cart'))

14. 结算

@app.route("/checkout")
def checkout():
    email = session['email']
    with sqlite3.connect('database.db') as con:
        cur = con.cursor()
        cur.execute("SELECT userId FROM users WHERE email = ?", (email, ))
        userId = cur.fetchone()[0]
        try:
            cur.execute("delete   FROM   kart WHERE userId = ?", (userId,))
            con.commit()
            msg = "Delete Successfully"
        except:
            con.rollback()
            msg = "Error occured"
    con.close()
    return redirect(url_for('root'))

后端完整代码

 import time

from flask import *
import sqlite3, hashlib, os
from flask import Flask, render_template, session
from flask_socketio import SocketIO, emit


# 摄像头参数
camera = None
detecting = False
from werkzeug.utils import secure_filename
import cv2
from PIL import Image
import numpy as np
app = Flask(__name__)
app.secret_key = 'random string'
socketio = SocketIO(app)
UPLOAD_FOLDER = 'static/uploads'
ALLOWED_EXTENSIONS = set(['jpeg', 'jpg', 'png', 'gif'])
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
# import detect
# model=detect.InitModel()
# model.model_init()
from ultralytics import YOLO
import cv2
model = YOLO("../best.pt")
from decimal import Decimal,ROUND_HALF_UP
def round_dec(n, d):
    s = '0.' + '0' * d
    return Decimal(n).quantize(Decimal(s), ROUND_HALF_UP)


def getLoginDetails():
    with sqlite3.connect('database.db') as conn:
        cur = conn.cursor()
        if 'email' not in session:
            loggedIn = False
            firstName = ''
            noOfItems = 0
        else:
            loggedIn = True
            cur.execute("SELECT userId, firstName FROM users WHERE email = ?", (session['email'], ))
            userId, firstName = cur.fetchone()
            cur.execute("SELECT count(productId) FROM kart WHERE userId = ?", (userId, ))
            noOfItems = cur.fetchone()[0]
    conn.close()
    return (loggedIn, firstName, noOfItems)

@app.route("/")
def root():
    loggedIn, firstName, noOfItems = getLoginDetails()
    with sqlite3.connect('database.db') as conn:
        cur = conn.cursor()
        cur.execute('SELECT productId, name,chineseName, price, description, image, stock FROM products')
        itemData = cur.fetchall()
        cur.execute('SELECT categoryId, name FROM categories')
        categoryData = cur.fetchall()
    itemData = parse(itemData)   
    return render_template('home.html', itemData=itemData, loggedIn=loggedIn, firstName=firstName, noOfItems=noOfItems, categoryData=categoryData)

@app.route("/add")
def admin():
    with sqlite3.connect('database.db') as conn:
        cur = conn.cursor()
        cur.execute("SELECT categoryId, name FROM categories")
        categories = cur.fetchall()
    conn.close()
    return render_template('add.html', categories=categories)

@app.route("/addItem", methods=["GET", "POST"])
def addItem():
    if request.method == "POST":
        name = request.form['name']
        price = float(request.form['price'])
        description = request.form['description']
        stock = int(request.form['stock'])
        categoryId = int(request.form['category'])

        #Uploading image procedure
        image = request.files['image']
        if image and allowed_file(image.filename):
            filename = secure_filename(image.filename)
            image.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
        imagename = filename
        with sqlite3.connect('database.db') as conn:
            try:
                cur = conn.cursor()
                cur.execute('''INSERT INTO products (name, price, description, image, stock, categoryId) VALUES (?, ?, ?, ?, ?, ?)''', (name, price, description, imagename, stock, categoryId))
                conn.commit()
                msg="added successfully"
            except:
                msg="error occured"
                conn.rollback()
        conn.close()
        print(msg)
        return redirect(url_for('root'))

@app.route("/remove")
def remove():
    with sqlite3.connect('database.db') as conn:
        cur = conn.cursor()
        cur.execute('SELECT productId, name, price, description, image, stock FROM products')
        data = cur.fetchall()
    conn.close()
    return render_template('remove.html', data=data)

@app.route("/removeItem")
def removeItem():
    productId = request.args.get('productId')
    with sqlite3.connect('database.db') as conn:
        try:
            cur = conn.cursor()
            cur.execute('DELETE FROM products WHERE productID = ?', (productId, ))
            conn.commit()
            msg = "Deleted successsfully"
        except:
            conn.rollback()
            msg = "Error occured"
    conn.close()
    print(msg)
    return redirect(url_for('root'))

@app.route("/displayCategory")
def displayCategory():
        loggedIn, firstName, noOfItems = getLoginDetails()
        categoryId = request.args.get("categoryId")
        with sqlite3.connect('database.db') as conn:
            cur = conn.cursor()
            cur.execute("SELECT products.productId, products.name,products.chineseName, products.price, products.image, categories.name FROM products, categories WHERE products.categoryId = categories.categoryId AND categories.categoryId = ?", (categoryId, ))
            data = cur.fetchall()
        conn.close()
        categoryName = data[0][5]
        data = parse(data)
        return render_template('displayCategory.html', data=data, loggedIn=loggedIn, firstName=firstName, noOfItems=noOfItems, categoryName=categoryName)

@app.route("/account/profile")
def profileHome():
    if 'email' not in session:
        return redirect(url_for('root'))
    loggedIn, firstName, noOfItems = getLoginDetails()
    return render_template("profileHome.html", loggedIn=loggedIn, firstName=firstName, noOfItems=noOfItems)

@app.route("/account/profile/edit")
def editProfile():
    if 'email' not in session:
        return redirect(url_for('root'))
    loggedIn, firstName, noOfItems = getLoginDetails()
    with sqlite3.connect('database.db') as conn:
        cur = conn.cursor()
        cur.execute("SELECT userId, email, firstName, lastName, address1, address2, zipcode, city, state, country, phone FROM users WHERE email = ?", (session['email'], ))
        profileData = cur.fetchone()
    conn.close()
    return render_template("editProfile.html", profileData=profileData, loggedIn=loggedIn, firstName=firstName, noOfItems=noOfItems)

@app.route("/account/profile/changePassword", methods=["GET", "POST"])
def changePassword():
    if 'email' not in session:
        return redirect(url_for('loginForm'))
    if request.method == "POST":
        oldPassword = request.form['oldpassword']
        oldPassword = hashlib.md5(oldPassword.encode()).hexdigest()
        newPassword = request.form['newpassword']
        newPassword = hashlib.md5(newPassword.encode()).hexdigest()
        with sqlite3.connect('database.db') as conn:
            cur = conn.cursor()
            cur.execute("SELECT userId, password FROM users WHERE email = ?", (session['email'], ))
            userId, password = cur.fetchone()
            if (password == oldPassword):
                try:
                    cur.execute("UPDATE users SET password = ? WHERE userId = ?", (newPassword, userId))
                    conn.commit()
                    msg="Changed successfully"
                except:
                    conn.rollback()
                    msg = "Failed"
                return render_template("changePassword.html", msg=msg)
            else:
                msg = "Wrong password"
        conn.close()
        return render_template("changePassword.html", msg=msg)
    else:
        return render_template("changePassword.html")

@app.route("/updateProfile", methods=["GET", "POST"])
def updateProfile():
    if request.method == 'POST':
        email = request.form['email']
        firstName = request.form['firstName']
        lastName = request.form['lastName']
        address1 = request.form['address1']
        address2 = request.form['address2']
        zipcode = request.form['zipcode']
        city = request.form['city']
        state = request.form['state']
        country = request.form['country']
        phone = request.form['phone']
        with sqlite3.connect('database.db') as con:
                try:
                    cur = con.cursor()
                    cur.execute('UPDATE users SET firstName = ?, lastName = ?, address1 = ?, address2 = ?, zipcode = ?, city = ?, state = ?, country = ?, phone = ? WHERE email = ?', (firstName, lastName, address1, address2, zipcode, city, state, country, phone, email))

                    con.commit()
                    msg = "Saved Successfully"
                except:
                    con.rollback()
                    msg = "Error occured"
        con.close()
        return redirect(url_for('editProfile'))

@app.route("/loginForm")
def loginForm():
    if 'email' in session:
        return redirect(url_for('root'))
    else:
        return render_template('login.html', error='')

@app.route("/login", methods = ['POST', 'GET'])
def login():
    if request.method == 'POST':
        email = request.form['email']
        password = request.form['password']
        if is_valid(email, password):
            session['email'] = email
            return redirect(url_for('root'))
        else:
            error = 'Invalid UserId / Password'
            return render_template('login.html', error=error)

@app.route("/productDescription")
def productDescription():
    loggedIn, firstName, noOfItems = getLoginDetails()
    productId = request.args.get('productId')
    with sqlite3.connect('database.db') as conn:
        cur = conn.cursor()
        cur.execute('SELECT productId, name, price, description, image, stock FROM products WHERE productId = ?', (productId, ))
        productData = cur.fetchone()
    conn.close()
    return render_template("productDescription.html", data=productData, loggedIn = loggedIn, firstName = firstName, noOfItems = noOfItems)

@app.route("/addToCart")
def addToCart():
    if 'email' not in session:
        return redirect(url_for('loginForm'))
    else:
        productId = int(request.args.get('productId'))
        with sqlite3.connect('database.db') as conn:
            cur = conn.cursor()
            cur.execute("SELECT userId FROM users WHERE email = ?", (session['email'], ))
            userId = cur.fetchone()[0]
            try:
                cur.execute("INSERT INTO kart (userId, productId) VALUES (?, ?)", (userId, productId))
                conn.commit()
                msg = "Added successfully"
            except:
                conn.rollback()
                msg = "Error occured"
        conn.close()
        return redirect(url_for('root'))

@app.route("/yoloPic", methods=['POST'])
def yoloPic():
    if 'email' not in session:
        return redirect(url_for('loginForm'))
    else:
        if 'image' not in request.files:
            return 'No file uploaded', 400

        image_file = request.files['image']
        if image_file.filename == '':
            return 'No file selected', 400
        name_list = []
        image = Image.open(image_file)
        np_array = np.array(image)

        # 将NumPy数组转换为OpenCV图像
        img = cv2.cvtColor(np_array, cv2.COLOR_RGB2BGR)
        # img = cv2.imread(image_file)
        # name_list = model.detect(name_list, img)

        res=model.predict(img, save=False, imgsz=640, conf=0.5)
        id_list = res[0].boxes.cls.cpu().numpy()
        namesMap = res[0].names
        for i in id_list:
            name_list.append(namesMap[i])
        # print(name_list)

        with sqlite3.connect('database.db') as conn:
            cur = conn.cursor()
            cur.execute("SELECT userId FROM users WHERE email = ?", (session['email'], ))
            userId = cur.fetchone()[0]
            product_id_name = {}
            cur.execute("SELECT productId,name FROM products ")
            res = cur.fetchall()
            for productId, name in res:
                product_id_name.update({name: productId})
            productIds = []
            for name in name_list:
                productIds.append(product_id_name[name])
            try:
                for productId in productIds:
                    cur.execute("INSERT INTO kart (userId, productId) VALUES (?, ?)", (userId, productId))
                    conn.commit()
                    msg = "Added successfully"
            except:
                conn.rollback()
                msg = "Error occured"
        conn.close()
        return redirect(url_for('cart'))
# # 检测函数
# # 摄像头参数
# camera = None
# detecting = False
# def detect(email):
#     global camera, detecting
#
#     while detecting:
#         if camera is not None:
#             success, frame = camera.read()  # 读取摄像头帧
#             # 在这里添加你的检测逻辑
#             # 如果检测到满足条件的商品,则跳出循环
#             name_list=[]
#             res = model.predict(frame, save=False, imgsz=640, conf=0.5)
#             id_list = res[0].boxes.cls.cpu().numpy()
#             namesMap = res[0].names
#             for i in id_list:
#                 name_list.append(namesMap[i])
#             print(name_list)
#             if len(name_list)!=0:
#                 with sqlite3.connect('database.db') as conn:
#                     cur = conn.cursor()
#                     cur.execute("SELECT userId FROM users WHERE email = ?", (email,))
#                     userId = cur.fetchone()[0]
#                     product_id_name = {}
#                     cur.execute("SELECT productId,name FROM products ")
#                     res = cur.fetchall()
#                     for productId, name in res:
#                         product_id_name.update({name: productId})
#                     productIds = []
#                     for name in name_list:
#                         productIds.append(product_id_name[name])
#                     try:
#                         for productId in productIds:
#                             cur.execute("INSERT INTO kart (userId, productId) VALUES (?, ?)", (userId, productId))
#                             conn.commit()
#                             msg = "Added successfully"
#                     except:
#                         conn.rollback()
#                         msg = "Error occured"
#                 conn.close()
#                 detecting = False
#                 return
#             # 将检测结果显示在Web界面上
#             ret, buffer = cv2.imencode('.jpg', frame)
#             frame = buffer.tobytes()
#             yield (b'--frame\r\n'
#                    b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n')
#
#
# @app.route('/start_detection')
# def start_detection():
#     global camera, detecting
#
#     if not detecting:
#         # 初始化摄像头
#         camera = cv2.VideoCapture(0)  # 这里的0表示默认摄像头设备
#         detecting = True
#
#     return '', 200
#
# @app.route('/video_feed')
# def video_feed():
#     global camera, detecting
#     email=session['email']
#     if detecting:
#         return Response(detect(email), mimetype='multipart/x-mixed-replace; boundary=frame')
#     else:
#         return redirect(url_for('cart'))
def detect(email):
    global camera, detecting
    pre_name_list = []
    while detecting:
        socketio.sleep(0.01)
        if camera is not None:
            success, frame = camera.read()  # 读取摄像头帧
            # 如果检测到满足条件的商品,则跳出循环
            name_list=[]

            res = model.predict(frame, save=False, imgsz=640, conf=0.7)
            id_list = res[0].boxes.cls.cpu().numpy()
            namesMap = res[0].names
            detectimg=res[0].plot()
            for i in id_list:
                name_list.append(namesMap[i])
            flag=len(name_list)!=0 and len(name_list)==len(pre_name_list)
            for i,j in zip(name_list,pre_name_list):
                if i==j:
                    continue
                else:
                    flag=False
                    break
            print(pre_name_list, name_list)
            pre_name_list=name_list
            if flag :
                with sqlite3.connect('database.db') as conn:
                    cur = conn.cursor()
                    cur.execute("SELECT userId FROM users WHERE email = ?", (email,))
                    userId = cur.fetchone()[0]
                    product_id_name = {}
                    cur.execute("SELECT productId,name FROM products ")
                    res = cur.fetchall()
                    for productId, name in res:
                        product_id_name.update({name: productId})
                    productIds = []
                    for name in name_list:
                        productIds.append(product_id_name[name])
                    try:
                        for productId in productIds:
                            cur.execute("INSERT INTO kart (userId, productId) VALUES (?, ?)", (userId, productId))
                            conn.commit()
                            msg = "Added successfully"
                    except:
                        conn.rollback()
                        msg = "Error occured"
                conn.close()
                detection_successful=True
            else:
                detection_successful = False
            # 将检测结果发送到客户端
            # print("detectimg",detectimg)
            # print("frame",frame)
            ret, buffer = cv2.imencode('.jpg', detectimg )
            frame_bytes = buffer.tobytes()
            socketio.emit('video_frame', frame_bytes)
            # time.sleep(1)
            if detection_successful:
                socketio.sleep(2)
                detecting = False
                socketio.emit('detection_result', 'success')  # 发送检测结果
@socketio.on('start_detection')
def start_detection():
    global camera, detecting

    if not detecting:
        # 初始化摄像头
        email=session['email']
        camera = cv2.VideoCapture(0)  # 这里的0表示默认摄像头设备
        detecting = True

        # 启动检测
        socketio.start_background_task(target=detect,email=email)

@socketio.on('disconnect')
def disconnect():
    global camera, detecting

    if detecting:
        # 停止检测
        detecting = False
        camera.release()

@app.route("/cart")
def cart():
    if 'email' not in session:
        return redirect(url_for('loginForm'))
    loggedIn, firstName, noOfItems = getLoginDetails()
    email = session['email']
    with sqlite3.connect('database.db') as conn:
        cur = conn.cursor()
        cur.execute("SELECT userId FROM users WHERE email = ?", (email, ))
        userId = cur.fetchone()[0]
        cur.execute("SELECT kart.id, products.chineseName, products.price, products.image FROM products, kart WHERE products.productId = kart.productId AND kart.userId = ?", (userId, ))
        products = cur.fetchall()
    totalPrice = Decimal(0)
    for row in products:
        totalPrice += Decimal(row[2])
    totalPrice=round_dec(totalPrice,2)
    return render_template("cart.html", products = products, totalPrice=totalPrice, loggedIn=loggedIn, firstName=firstName, noOfItems=noOfItems)
@app.route("/checkout")
def checkout():
    email = session['email']
    with sqlite3.connect('database.db') as con:
        cur = con.cursor()
        cur.execute("SELECT userId FROM users WHERE email = ?", (email, ))
        userId = cur.fetchone()[0]
        try:
            cur.execute("delete   FROM   kart WHERE userId = ?", (userId,))
            con.commit()
            msg = "Delete Successfully"
        except:
            con.rollback()
            msg = "Error occured"
    con.close()
    return redirect(url_for('root'))
@app.route("/removeFromCart")
def removeFromCart():
    if 'email' not in session:
        return redirect(url_for('loginForm'))
    email = session['email']
    id = int(request.args.get('id'))
    with sqlite3.connect('database.db') as conn:
        cur = conn.cursor()
        cur.execute("SELECT userId FROM users WHERE email = ?", (email, ))
        userId = cur.fetchone()[0]
        try:
            cur.execute("DELETE FROM kart WHERE id= ?", (id,))
            conn.commit()
            msg = "removed successfully"
        except:
            conn.rollback()
            msg = "error occured"
    conn.close()
    return redirect(url_for('cart'))

@app.route("/logout")
def logout():
    session.pop('email', None)
    return redirect(url_for('root'))

def is_valid(email, password):
    con = sqlite3.connect('database.db')
    cur = con.cursor()
    cur.execute('SELECT email, password FROM users')
    data = cur.fetchall()
    for row in data:
        if row[0] == email and row[1] == hashlib.md5(password.encode()).hexdigest():
            return True
    return False

@app.route("/register", methods = ['GET', 'POST'])
def register():
    if request.method == 'POST':
        #Parse form data    
        password = request.form['password']
        email = request.form['email']
        firstName = request.form['firstName']
        lastName = request.form['lastName']
        address1 = request.form['address1']
        address2 = request.form['address2']
        zipcode = request.form['zipcode']
        city = request.form['city']
        state = request.form['state']
        country = request.form['country']
        phone = request.form['phone']

        with sqlite3.connect('database.db') as con:
            try:
                cur = con.cursor()
                cur.execute('INSERT INTO users (password, email, firstName, lastName, address1, address2, zipcode, city, state, country, phone) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)', (hashlib.md5(password.encode()).hexdigest(), email, firstName, lastName, address1, address2, zipcode, city, state, country, phone))

                con.commit()

                msg = "Registered Successfully"
            except:
                con.rollback()
                msg = "Error occured"
        con.close()
        return render_template("login.html", error=msg)

@app.route("/registerationForm")
def registrationForm():
    return render_template("register.html")

def allowed_file(filename):
    return '.' in filename and \
            filename.rsplit('.', 1)[1] in ALLOWED_EXTENSIONS

def parse(data):
    ans = []
    i = 0
    while i < len(data):
        curr = []
        for j in range(7):
            if i >= len(data):
                break
            curr.append(data[i])
            i += 1
        ans.append(curr)
    return ans

if __name__ == '__main__':
    socketio.run(app, debug=True)
    # app.run(debug=True)

到了这里,关于利用yolov8零售商品识别实现的智能结算系统 yolo+后端flask+数据库sqlite+前端html(从零开始,全流程教学)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • 基于YOLOv8深度学习的智能车牌检测与识别系统【python源码+Pyqt5界面+数据集+训练代码】目标检测、深度学习实战

    基于YOLOv8深度学习的智能车牌检测与识别系统【python源码+Pyqt5界面+数据集+训练代码】目标检测、深度学习实战

    《博主简介》 小伙伴们好,我是阿旭。专注于人工智能、AIGC、python、计算机视觉相关分享研究。 ✌ 更多学习资源,可关注公-仲-hao:【阿旭算法与机器学习】,共同学习交流~ 👍 感谢小伙伴们点赞、关注! 《------往期经典推荐------》 一、AI应用软件开发实战专栏【链接】

    2024年02月20日
    浏览(47)
  • 数字化商品管理:革新鞋服零售模式,引领智能商业新时代

    数字化商品管理:革新鞋服零售模式,引领智能商业新时代

    随着科技的快速发展,数字化浪潮席卷各行各业,鞋服零售企业亦不例外。在这个新时代,数字化商品管理不仅成为鞋服零售企业革新的关键,更是其引领智能商业浪潮的重要引擎。本文将围绕数字化商品管理如何深刻影响鞋服零售模式,并推动其迈向智能商业新时代进行深

    2024年02月20日
    浏览(13)
  • YOLOv8+PyQt+OpenCV实现数字式仪表读数和指针式仪表读数识别(二)

    YOLOv8+PyQt+OpenCV实现数字式仪表读数和指针式仪表读数识别(二)

    章(一)内容为不同种类仪表识别和数字式仪表读数识别,这一章介绍 两种指针式仪表读数识别方法 ,一种为 非360度指针式仪表 ,一种为 360度指针式仪表 。效果如下所示。 指针式仪表识别效果 360度指针式仪表识别效果  数字式仪表识别效果 数字式仪表和指针式仪表检测视

    2024年03月18日
    浏览(13)
  • YOLOv8+PyQt+OpenCV实现数字式仪表读数和指针式仪表读数识别(一)

    YOLOv8+PyQt+OpenCV实现数字式仪表读数和指针式仪表读数识别(一)

    最近放假看到YOLOv8一直在更新,想着在家无聊把本科毕设重新做了下,之前用的是YOLOv5,下载了YOLOv8最新版把项目迁移了过来,相比于v5来说YOLOv8变化还是挺大的,功能更加集成了,话不多说,直接上 结果图片和最后的检测视频 。 数字式仪表识别效果 指针式仪表识别效果

    2024年02月19日
    浏览(18)
  • 助力智能密集人群检测计数,基于YOLOv8全系列模型【n/s/m/l/x】开发构建通用场景下密集人群检测计数识别系统

    助力智能密集人群检测计数,基于YOLOv8全系列模型【n/s/m/l/x】开发构建通用场景下密集人群检测计数识别系统

    在一些人流量比较大的场合,或者是一些特殊时刻、时段、节假日等特殊时期下,密切关注当前系统所承载的人流量是十分必要的,对于超出系统负荷容量的情况做到及时预警对于管理团队来说是保障人员安全的重要手段,本文的主要目的是想要基于通用的数据开发构建用于

    2024年01月23日
    浏览(11)
  • 如何运行代码mikel-brostrom/yolov8_tracking实现目标识别和跟踪?

    如何运行代码mikel-brostrom/yolov8_tracking实现目标识别和跟踪?

    https://github.com/mikel-brostrom/yolov8_tracking 项目名:Real-time multi-object tracking and segmentation using Yolov8 (1)它的识别和分割是YOLO8完成的。它的多目标追踪是由后面四种算法实现的(botsort,bytetrack,ocsort,strongsort) (2)它这个是实时的Real-time,识别、跟踪、分割的速度很快 这个代码是

    2024年02月02日
    浏览(14)
  • OpenCV与AI深度学习 | 实战 | YOLOv8自定义数据集训练实现手势识别 (标注+训练+预测 保姆级教程)

    OpenCV与AI深度学习 | 实战 | YOLOv8自定义数据集训练实现手势识别 (标注+训练+预测 保姆级教程)

    本文来源公众号 “OpenCV与AI深度学习” ,仅用于学术分享,侵权删,干货满满。 原文链接:实战 | YOLOv8自定义数据集训练实现手势识别 (标注+训练+预测 保姆级教程)     本文将手把手教你用YoloV8训练自己的数据集并实现手势识别。 【1】安装torch, torchvision对应版本,这里先

    2024年04月23日
    浏览(51)
  • YOLOv8改进 | 进阶实战篇 | 利用YOLOv8进行视频划定区域目标统计计数

    YOLOv8改进 | 进阶实战篇 | 利用YOLOv8进行视频划定区域目标统计计数

    Hello,各位读者, 最近会给大家发一些进阶实战的讲解 ,如何利用YOLOv8现有的一些功能进行一些实战, 让我们不仅会改进YOLOv8,也能够利用YOLOv8去做一些简单的小工作,后面我也会将这些功能利用PyQt或者是pyside2做一些小的界面给大家使用。 在开始之前给大家推荐一下我的

    2024年01月20日
    浏览(25)
  • YOLOv8改进 | 检测头篇 | 利用DBB重参数化模块魔改检测头实现暴力涨点 (支持检测、分割、关键点检测)

    YOLOv8改进 | 检测头篇 | 利用DBB重参数化模块魔改检测头实现暴力涨点 (支持检测、分割、关键点检测)

    本文给大家带来的改进机制是 二次创新 的机制,二次创新是我们发表论文中关键的一环,本文给大家带来的二次创新机制是通过 DiverseBranchBlock(DBB) 模块来改进我们的检测头形成一个新的检测头Detect_DBB,其中DBB是一种重参数化模块,其训练时采用复杂结构,推理时使用单分支

    2024年01月16日
    浏览(39)
  • YOLOv8 视频识别

    YOLOv8 是一种目标检测算法,用于识别视频中的物体。要控制视频识别中的帧,可以通过以下方式来实现: 设置帧率:可以通过设置视频的帧率来控制视频的播放速度,从而影响视频识别的速度。 跳帧处理:可以通过跳帧的方式来控制视频识别的处理帧数,例如每隔几帧进行

    2024年01月23日
    浏览(17)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包