数独图像轮廓排序异常求助:修正从右到左的ROI生成顺序
解决数独轮廓从下到上、从右到左排序的跳序问题
你的核心问题是同行轮廓的y坐标存在1-3像素的微小差异,直接按y逆序排序会导致行内轮廓乱序。要实现从底部开始、从右到左的ROI生成,需要先按行分组,再对每行内部按x逆序,最后按行的y值从大到小排列。
修正后的排序逻辑
替换你原来的sort_contours函数,采用分组排序的方式:
def sort_contours(contours, row_threshold=10): # 获取所有轮廓的 bounding box bounding_boxes = [cv2.boundingRect(c) for c in contours] # 将轮廓和 bounding box 配对,便于后续处理 contour_box_pairs = list(zip(contours, bounding_boxes)) # 第一步:先按 y 坐标从大到小排序(初步区分行) contour_box_pairs.sort(key=lambda pair: pair[1][1], reverse=True) # 第二步:按行分组,把 y 差小于阈值的归为同一行 rows = [] current_row = [contour_box_pairs[0]] for pair in contour_box_pairs[1:]: prev_y = current_row[-1][1][1] curr_y = pair[1][1] if abs(prev_y - curr_y) < row_threshold: current_row.append(pair) else: rows.append(current_row) current_row = [pair] rows.append(current_row) # 加入最后一行 # 第三步:每行内按 x 坐标从大到小排序(实现从右到左) sorted_pairs = [] for row in rows: row_sorted = sorted(row, key=lambda pair: pair[1][0], reverse=True) sorted_pairs.extend(row_sorted) # 拆分回轮廓列表 sorted_contours = [pair[0] for pair in sorted_pairs] return sorted_contours
代码解释
- 初步按y排序:先把所有轮廓按顶部y坐标从大到小排,让底部的行先出现,同时把同行的轮廓尽量聚集在一起。
- 行分组:遍历排序后的轮廓,把y值差异小于
row_threshold(可根据你的数独单元格高度调整,比如设为单元格高度的1/3)的轮廓归为同一行,解决微小y差导致的行混乱问题。 - 行内逆序:每行内部按x坐标从大到小排序,这样每行的轮廓从右到左排列,符合你的需求。
- 合并结果:把所有行的轮廓按顺序合并,得到最终的排序结果。
其他优化建议
- 你的
contours_ocr函数中,保存ROI再读取的操作可以简化,直接用内存中的图像传给pytesseract,避免IO开销:# 替换原来的保存再读取逻辑 ocr = pytesseract.image_to_string(roi, config='--psm 6') - 确保
sudoku数组的长度是81(9x9),避免索引越界。
为什么原方案失效
你之前手动修改相邻轮廓y值的逻辑只处理了相邻的两个轮廓,无法覆盖同一行中不相邻的轮廓,而且没有对行内的x坐标做排序,自然无法实现从右到左的顺序。
内容的提问来源于stack exchange,提问作者Vitor L.
相关产品推荐
相关产品推荐

