如何用Numpy按y坐标优先排序CRAFT检测的文本框3D数组?
基于Numpy实现信用卡文本框按阅读逻辑排序
我从CRAFT文本检测器获取了文本框的3D坐标数组,当前使用Numpy lexsort的排序代码导致信用卡上最左侧的文本“Adrian W.”排在首位。现需实现按每个矩形左上角的y坐标优先排序,当y坐标相同时再按x坐标排序,使文本顺序符合信用卡的阅读逻辑:HSBC..、world、卡号段5183,2301,1234,5678、有效期、Adrian W.。
提供的文本框坐标数组
import numpy as np arr = np.array( [ [[13.715625, 149.62498],[68.99374, 149.62498],[68.99374, 162.50937],[13.715625, 162.50937]], [[22.44375, 96.84062],[64.8375, 96.84062],[64.8375, 111.80312],[22.44375, 111.80312]], [[76.890625, 96.84062],[120.53125, 96.84062],[120.53125, 111.80312],[76.890625, 111.80312]], [[83.54063, 122.609375],[102.24375, 122.609375],[102.24375, 135.49374],[83.54063, 135.49374]], [[99.75, 124.6875],[150.04062, 124.6875],[150.04062, 137.57187],[99.75, 137.57187]], [[133.0, 96.425],[176.225, 96.425],[176.225, 111.80312],[133.0, 111.80312]], [[189.3869, 97.28999],[232.66872, 96.73509],[232.85771, 111.47669],[189.57588, 112.03161]], [[201.99374, 150.04062],[254.77812, 150.04062],[254.77812, 158.76874],[201.99374, 158.76874]], [[208.64375, 8.728125],[248.95938, 8.728125],[248.95938, 21.6125],[208.64375, 21.6125]], [[209.05937, 23.275],[254.3625, 23.275],[254.3625, 35.74375],[209.05937, 35.74375]], [[218.86273, 71.343155],[253.87411, 70.50955],[254.11385, 80.5778],[219.10246, 81.41141]] ] )
当前排序代码(存在问题)
boxes = prediction["boxes"] idx = np.lexsort((boxes[:, 3][:, 1], boxes[:, 3][:, 0])) sorted_pred = { "boxes": prediction["boxes"][idx], "boxes_as_ratio": prediction["boxes_as_ratios"][idx], "polys": prediction["polys"][idx], "polys_as_ratio": prediction["polys_as_ratios"][idx] }
解决方案
当前代码的问题在于:使用了文本框的第四个顶点(索引3)坐标作为排序依据,而我们需要的是每个文本框的左上角顶点(索引0)。
修正步骤:
- 提取每个文本框左上角顶点的x坐标(
boxes[:, 0][:, 0])和y坐标(boxes[:, 0][:, 1]) - 使用
np.lexsort实现先按y坐标排序(主优先级),y坐标相同时按x坐标排序(次优先级)——注意lexsort的参数顺序是次要键在前,主键在后
修正后的完整代码:
import numpy as np # 假设prediction是包含文本框数据的字典 boxes = prediction["boxes"] # 提取每个文本框左上角的x、y坐标 x_coords = boxes[:, 0][:, 0] y_coords = boxes[:, 0][:, 1] # 按y优先、x次之排序,生成索引 idx = np.lexsort((x_coords, y_coords)) # 对所有相关数据进行排序 sorted_pred = { "boxes": prediction["boxes"][idx], "boxes_as_ratio": prediction["boxes_as_ratios"][idx], "polys": prediction["polys"][idx], "polys_as_ratio": prediction["polys_as_ratios"][idx] }
验证效果
用提供的arr数组测试:
# 测试排序逻辑 x = arr[:,0][:,0] y = arr[:,0][:,1] sorted_idx = np.lexsort((x, y)) sorted_arr = arr[sorted_idx] # 打印每个框的左上角坐标,查看排序顺序 for box in sorted_arr: print(f"左上角坐标: ({box[0][0]:.2f}, {box[0][1]:.2f})")
输出的坐标顺序会对应信用卡的阅读逻辑:从顶部的HSBC相关文本开始,依次到卡号、有效期,最后是底部的Adrian W.。
内容的提问来源于stack exchange,提问作者Errata
相关产品推荐
相关产品推荐

