当前位置:   article > 正文

核酸检测结果识别系统——核心技术_opencv识别核酸检测

opencv识别核酸检测

目录

源代码

技术算法讲解

组成部分

easyocr

opencv

excel表和数据库

Pyecharts可视化界面

效果展示

运行控制


源代码

abcdefg-png/-system (github.com)

技术算法讲解

组成部分

easyocr图像文字提取+opencv颜色识别+正则表达式结果匹配+Python写入Excel和数据库+pyecharts可视化界面 + schedule控制挂载运行;

HTML+CSS+JS+jquery+bootstrap(前端)+ PHP(后端)+ Nginx反向代理 + pm2(项目部署)

easyocr

easyocr是python 2021年推出的第三方包,可以非常精准的识别、提取图片文字(亲测有效)。这项功能主要被用来提取学生的核酸检测时间。下面是easyocr的具体使用:

  1. f = open('result.txt', 'w')
  2. for filename in os.listdir(directory_name):
  3.    reader = easyocr.Reader(['ch_sim', 'en'], gpu=False)  # GPU or CPU
  4.    result = reader.readtext(directory_name + r'/' + filename, detail=0)
  5.    result = str.join(result)
  6.    f.write(result)
  7.    f.write("\n")

这里要注意两点,['ch_sim', 'en']是识别语言的列表(中、英文),如果需要其他语言可以去搜它对应的代码。gpu=false 表示我的电脑配置没有gpu,设置成用cpu跑深度学习的代码。

另外,reader.readtext() 是不支持中文路径的,读取的路径一定要注意!

读取完图片文字后,我们把他写入一个txt中,下面要从杂乱的文字中提取出学生的核酸检测时间:

  1.    try:
  2.        timeresult = re.search('采集时间[\d,\-,:,.]*', result) # 获取采集时间
  3.        timeres.append(timeresult.group()[4:]) # 去掉前四个字“采集时间”
  4.    except Exception as err:
  5.        timeres.append("时间匹配失败")

这里我们一定要加入异常处理,防止因为匹配失败而直接报错中断运行。

opencv

本身是打算用easyocr直接提取“阴性”这两个字,但是发现这两个字实在不好提取。所以决定用opencv的颜色识别解决结果的判断问题。首先我们列出一个颜色清单,命名为colorList.py。为了识别更加准确,我们只留下红绿两种颜色。

  1. def getColorList():
  2.    dict = collections.defaultdict(list)
  3.    # 红色
  4.    lower_red = np.array([156, 43, 46])
  5.    upper_red = np.array([180, 255, 255])
  6.    color_list = []
  7.    color_list.append(lower_red)
  8.    color_list.append(upper_red)
  9.    dict[r'colorList/red'] = color_list
  10.    # 绿色
  11.    lower_green = np.array([35, 43, 46])
  12.    upper_green = np.array([77, 255, 255])
  13.    color_list = []
  14.    color_list.append(lower_green)
  15.    color_list.append(upper_green)
  16.    dict[r'coloList/green'] = color_list
  17.    return dict

之后用opencv函数进行颜色判断;但cv2.imwrite函数只支持jpg图片,所以我们在网站收集图片时,可以将目标图片进行.jpg文件转换。之后import刚刚的colorList,使用opencv识别图片的颜色。

  1. import colorList
  2. def get_color(frame):
  3.    hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
  4.    maxsum = -100
  5.    color = None
  6.    color_dict = colorList.getColorList()
  7.    for d in color_dict:
  8.        mask = cv2.inRange(hsv, color_dict[d][0], color_dict[d][1])
  9.        cv2.imwrite(d + '.jpg', mask) # 这里一定要保证,读取的图片是jpg
  10.        binary = cv2.threshold(mask, 127, 255, cv2.THRESH_BINARY)[1]
  11.        binary = cv2.dilate(binary, None, iterations=2)
  12.        cnts, hiera = cv2.findContours(binary.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
  13.        sum = 0
  14.        for c in cnts:
  15.            sum += cv2.contourArea(c)
  16.        if sum > maxsum:
  17.            maxsum = sum
  18.            color = d
  19.    return color

excel表和数据库

为了方便管理者导出,我们用python将结果写入了excel表格;为了做出可视化界面,我们也需要将结果写入database。数据库的建立比较简单,分为四个字段:

字段数据类型
sno(学号)varchar
sname(姓名)varchar
time_result(时间检测结果)varchar
test_result(检测结果)varchar

python写入excel表格的操作比较简单,另外,如果直接在浏览器输入.xlsx的文件地址,可以直接下载获取,也是十分方便。

在写入之前,我们需要先清理干净excel表格,我选择直接删除Sheet1,然后新建一张。做数据库也是一样,每次清理一次数据库,防止旧数据干扰新一次的检测。刷新后,写入本次的结果。

  1. db = pymysql.connect(host='localhost', user='', passwd='', port=3306, db='hesuan_result_collection')
  2. cursor = db.cursor()
  3. bg = op.load_workbook(r"result.xlsx")  # 应先将excel文件放入到工作目录下
  4. bg.remove(bg["Sheet1"])
  5. bg.create_sheet("Sheet1", index=0)
  6. sheet = bg["Sheet1"]
  7. sheet.cell(1, 1, "学号")
  8. sheet.cell(1, 2, "姓名")
  9. sheet.cell(1, 3, "检测时间")
  10. sheet.cell(1, 4, "检测结果") # 刷新excel表格的数据
  11. sql_delete = "Update xinan set time_result = '' , test_result = '' "
  12. cursor.execute(sql_delete)
  13. db.commit()   # 刷新数据库的数据
  14. if len(timeres) == len(testres):
  15.    for i in range(1, len(timeres) + 1):
  16.        sql_fetch_name = "select sname from xinan where sno = '%s' " % student_sno[i - 1] # 获取学号对应的姓名
  17.        cursor.execute(sql_fetch_name)
  18.        
  19.        sheet.cell(i + 1, 1, student_sno[i - 1])
  20.        try:
  21.            sheet.cell(i + 1, 1, student_sno[i - 1])
  22.        except Exception as err:
  23.            sheet.cell(i + 1, 1, "找不到姓名")
  24.        sheet.cell(i + 1, 3, timeres[i - 1])
  25.        sheet.cell(i + 1, 4, testres[i - 1])  # 分别写入学号、姓名、检测时间、检测结果
  26.        bg.save(r"result.xlsx")  # 对文件进行保存
  27.        
  28.        sql_update = "UPDATE `xinan` " \
  29.                     "SET `time_result` ='%s' , `test_result` = '%s' " \
  30.                     "WHERE sno = '%s'; " % (timeres[i - 1], testres[i - 1], student_sno[i - 1])
  31.        try:
  32.            sql_update_result = cursor.execute(sql_update)
  33.            db.commit() # 提交数据并保存
  34.        except Exception as err:
  35.            print("数据库写入失败:", err) # 这里同样也要加入异常处理
  36. else:
  37.    print("长度不匹配")
  38. print("finished")

Pyecharts可视化界面

做好了算法部分,我们也要能够展示实时提交的情况。这样可以更方便班委管理,及时催促指定同学提交核酸检测报告。首先我们连接数据库,写好相关的sql语句:

  1. import pymysql
  2. import main
  3. db = pymysql.connect(host='localhost', user='', passwd='', port=3306, db='hesuan_result_collection')
  4. cursor = db.cursor() # 数据库连接
  5. sql_find_failed = "SELECT DISTINCT sname,sno,time_result,test_result FROM xinan WHERE time_result = '时间匹配失败' or test_result = '结果存疑'" # 查找检测失败的同学名单
  6. sql_readyto_submit = "SELECT DISTINCT sname,sno,time_result,test_result FROM xinan " \
  7. "WHERE time_result = '时间匹配失败' or test_result = '结果存疑'" \
  8. "or time_result = '' or test_result = ''" # 查找需要重新提交的同学名单,包括结果为空和结果错误的总和
  9. main.student_failed = cursor.execute(sql_find_failed)
  10. main.student_left = main.student_num - main.student_checked - main.student_failed

之后使用sql查找的结果,制作饼图和表格 

饼图:

  1. def pie_base():
  2. label = ['识别成功', '未提交', '识别错误']
  3. values = [main.student_checked, main.student_left, main.student_failed] # 计算的三个变量制作饼图,识别成功+未提交+识别错误 == 所有学生
  4. c = (
  5. Pie()
  6. .add("", [list(z) for z in zip(label, values)])
  7. .set_global_opts(title_opts=opts.TitleOpts(title="20信安提交结果"))
  8. .set_series_opts(label_opts=opts.LabelOpts(formatter="{b}:{c}人 {d}%")) # 值得一提的是,{d}%为百分比
  9. )
  10. return c

表格:

  1. def table_base():
  2. cursor.execute(sql_find_failed)
  3. temp = cursor.fetchall() # 获取全部的结果
  4. failed_match = []
  5. for i in temp:
  6. x = list(i)
  7. failed_match.append(x) # 这里fetchall()函数返回的是元组,需要将元组转成列表进行表格制作
  8. table = Table()
  9. headers = ["学号", "姓名", "检测时间", "检测结果"]
  10. rows = failed_match
  11. table.add(headers, rows).set_global_opts(
  12. title_opts=opts.ComponentTitleOpts(title="识别失败名单")
  13. )
  14. return table

 布局设置:

  1. def page_simple_layout():
  2. page = Page(layout=Page.SimplePageLayout) # 简单布局
  3. page.add(
  4. pie_base(), # 展示饼图
  5. table_base(), # 展示识别失败名单
  6. table_base2(), # 展示
  7. )
  8. page.render("./result.html")
  9. if __name__ == "__main__":
  10. page_simple_layout()

效果展示

运行控制

使用python的schedule进行运行控制,我们可以有很多控制方法,将这个文件设置成run.py,之后将他用pm2或者nohup挂载运行即可。

  1. import schedule
  2. import os
  3. def run():
  4.    os.system("python view.py")
  5. schedule.every().day.at("10:30").do(run)  # 每天的10:30执行一次任务
  6. # schedule.every().monday.do(run) # 每周一的这个时候执行一次任务
  7. # schedule.every().hour.do(run) # 每隔一小时执行一次任务
  8. while True:
  9.    schedule.run_pending()  # run_pending:运行所有可以运行的任务

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/AllinToyou/article/detail/419677
推荐阅读
相关标签
  

闽ICP备14008679号