Skip to content

关于图书馆识别书的编号并链接mysql库项目的代码解析和分析

(因为自己的代码实在拉跨所以请教了同学并仔细研究了他的代码)

幕截图 2024-07-04 22590

findContours函数*1*用于查找给定二值图像erosion中的轮廓,并以层次结构的形式返回轮廓及其关系。参数RETR_TREE表示按照轮廓之间的父子关系构建树形结构,CHAIN_APPROX_NONE`则保留每个轮廓的所有像素点信息。

对于找到的轮廓contours,循环遍历它们,通过调用cv2.contourArea(contour)2计算每个轮廓的面积。如果某个轮廓的面积小于100,说明它可能是噪声或较小的对象,程序会将其添加到fill列表中。

最后,cv2.fillPoly()函数用于填充图像(erosion),使用指定的颜色(这里是白色 (255, 255, 255))来填充那些满足条件(面积小于100)的轮廓。这一步可能用于分割图像,去除小物体或标记特定区域。

幕截图 2024-07-04 23021

cv2.findContours 函数用于从二进制图像(阈值化的图像)中查找轮廓。参数说明如下:

  1. thresh 是要分析的二值图像,通常是通过某种边缘检测或阈值化操作得到的。
  2. mode 设定轮廓检索的方式,这里是 cv2.RETR_TREE,意味着会返回一个层次结构的轮廓树,每个轮廓都有其父轮廓,表示轮廓之间的嵌套关系。
  3. method 决定了轮廓近似的方式,这里设置为 cv2.CHAIN_APPROX_NONE,表示保留轮廓上的每一个像素点,以便获得更精确的形状。

这段代码的作用是:

  • 寻找thresh图像中的轮廓。
  • 对于找到的每个轮廓(contour),计算它的面积(cv2.contourArea)。
  • 如果轮廓的面积在给定的阈值范围内(这里假设小于3000),则计算轮廓的边界框(cv2.boundingRect),这是围绕轮廓的一个最小矩形区域。
  • 最后,它会在原始图像上绘制这个矩形框,颜色为绿色,线条宽度为2。12

执行这段代码后,你会看到thresh图像中的小面积轮廓都被标记了出来,形成绿色的矩形框。

幕截图 2024-07-04 23105

  1. 使用os.path.join创建当前文件夹的完整路径,如./moban/folder
  2. 判断该路径是否为实际存在的目录(即isdir返回True)。
  3. 如果是目录,使用列表推导式找出所有的.jpg文件,存入变量files
  4. 对于找到的每个文件,读取成灰度图像(cv2.imread),并将其添加到与value关联的模板列表中,如果value对应的列表不存在则新建。

接着,对于每一个模板列表(template_list):

  • 循环遍历列表中的每个模板(template)。
  • 对模板进行预处理操作,包括二值化(阈值处理)、腐蚀和膨胀(可选)、高斯模糊以及缩放。这些操作都是为了提高模板匹配的质量。
  • 处理后的模板替换原列表中的对应项。
  • cv2.threshold()用于二值化,cv2.dilate()cv2.erode()用于形态学操作,cv2.GaussianBlur()用于高斯滤波,cv2.resize()用于缩放图像。cv2.imshow()用于显示临时处理过的模板,但在这个上下文中并没有实际调用,因为cv2.waitKey(0)1通常会在交互式环境中等待按键事件,而这里没有显示窗口。

幕截图 2024-07-04 23133

img_thread = threading.Thread(target=self.recognize_wrapper, args=()) 创建了一个新的线程 img_thread,它的目标(target)是调用函数 self.recognize_wrappersetDaemon(True) 被用来设置这个线程为守护线程,这意味着当主线程(即最初的 if __name__ == '__main__': 中的部分)结束时,这个子线程也会随之结束。

img_thread.start() 启动了线程,而 img_thread.join() 是为了让主线程等待 img_thread 完成再继续执行后续操作。这样做的目的是保证主线程在处理结果之前,recognize_wrapper 已经完成了图像识别的工作。

self.result_queue.get() 用于从队列中获取 img_thread 的识别结果。之后对图片进行了腐蚀和缩小的操作(cv2.erodeself.reduce_img),以及轮廓检测和模板匹配。

幕截图 2024-07-04 23152

  1. 计算轮廓的面积(area = cv2.contourArea(contour)1
  2. 使用条件语句过滤掉面积太小(小于100像素)或过大(大于50000像素)的轮廓(if 0 < area < 100 ... area > 50000:)。
  3. 如果轮廓满足条件,绘制矩形框到roi区域(cv2.rectangle())。
  4. 提取并裁剪感兴趣的图像部分(img = roi[y:y + h, x:x + w])。
  5. 可能保存这个裁剪的图片以便后续处理(cv2.imwrite())。
  6. 对于每个裁剪的图片,尝试找到与某个模板的最佳匹配(这部分代码未完全展示,但提到best_matchbest_score用于评估匹配程度)。

具体来说,这部分代码可能是在进行物体检测或图像分割的过程中,筛选出感兴趣的部分,并对其进行单独处理或进一步的模板匹配分析。

幕截图 2024-07-04 23184

  1. 使用cv2.matchTemplate函数计算原始图像img与模板的相似度得分(这里使用的是TM_CCOEFF_NORMED方法,得分越接近1表示匹配度越高)。
  2. 找到匹配得分最高的部分(通过cv2.minMaxLoc),并更新best_scorebest_match(模板值)。
  3. 如果未找到匹配,跳过该模板继续下一次迭代。
  4. 循环结束后,输出最终的最佳匹配模板值best_match,并在图像上标记这个位置。
  5. best_match添加到结果列表result中,并将这些值组合成字符串result_str,展示在文本编辑框中。
  6. 最后尝试连接数据库并将识别结果存储起来(这部分的具体行为依赖于connect_sql函数,但显然用于保存识别信息)。

完成识别之后就要匹配mysql数据库中的书籍名称

  1. 连接数据库:
db = pymysql.connect(host=host, user=user, passwd=passwd, db=db2, charset='utf8')

使用pymysql库创建数据库连接,参数包括主机地址(host)、用户名(user)、密码(passwd)和要连接的数据库名(db2),以及字符集设置为’utf8’。

  1. 创建游标:
cursor = db.cursor()

创建一个游标对象,用于执行SQL语句和获取查询结果。

  1. 构建SQL查询:
sql = "SELECT bookname FROM library WHERE bookid = %s"

定义一个SQL查询语句,选择library表中bookid为\(result_str\)的bookname字段。

  1. 尝试执行查询:
try:
    cursor.execute(sql, result_str)

尝试执行SQL查询,将\(result_str\)作为占位符插入查询中。

  1. 获取并处理查询结果:
results = cursor.fetchall()
for row in results:
    print('查询结果:', row)
    self.textEdit.append(f"查询结果:{row}")

执行查询后,获取所有结果,遍历每一行并打印查询结果到self.textEdit(UI组件)中。

  1. 错误处理:如果执行时发生错误,捕获pymysql.Error异常,并在控制台打印错误信息,并在self.textEdit中添加错误消息。

  2. 关闭连接:

finally:
    db.close()

最后无论查询是否成功,都会确保关闭与数据库的连接以释放资源。

### 如何录入数书籍

  1. 尝试连接数据库

    try:
        db = pymysql.connect(host='8.147.233.239', user='root', passwd='team2111', db='ryp', charset='utf8')
    except pymysql.Error as e:
        print("数据库连接失败:", str(e))
        return
    

    使用 pymysql.connect() 函数尝试连接到指定的服务器(IP地址 ‘8.147.233.239’,用户名 ‘root’,密码 ‘team2111’),选择数据库 ‘ryp’,并设置字符集为 ‘utf8’。

  2. 创建游标:

    cursor = db.cursor()
    

    获取数据库连接的游标,用于执行SQL命令。

  3. 构造SQL查询:

    sql = "INSERT INTO book (id, name) VALUES (%s, %s)"
    

    定义要插入数据的SQL语句,这里假设有一个 ‘book’ 表,有’id’ 和 ‘name’ 两个字段。

  4. 尝试执行SQL并提交事务:

    try:
        cursor.execute(sql, (id, name))
        db.commit()
        print("数据插入成功")
    except pymysql.Error as e:
        db.rollback()
        print("数据插入失败:", str(e))
    

    使用 cursor.execute() 执行 SQL 插入操作,然后调用 db.commit() 提交事务。如果在这个阶段发生错误,则回滚事务(db.rollback())并打印错误信息。

  5. 关闭数据库连接:

    Python
    finally:
        db.close()