关于大图片的小目标的检测方法:将图片拆成四个分开去放到目标去训练
1 概述
在yolov5 的网络模型中大抵输入的图片为640*640,如果是3000 * 2000的图片去检测大概100像素左右的目标,会比较容易漏掉,这大概也和我的数据值过于少有关。所以我这种也算是一种数据增强的方式!
方法: 暴力搜索 和 带方向的暴力搜索
2 环境
- ubuntu 18.04
- pycharm2020.01
- yolov5 的要求环境
3 暴力搜索
3.1思路:
参考上图:
- 在给定的图片(width,height),以他们的中心点作为 起始点 centerpoint = (width/2 , height/2)
- 读取图片对应的 label 的文件,获得每个gtbox 的中心点,将其放入集合 - pointsList
- 设定阈值threshold,通过该阈值建立了矩形面积,如果gtbox 的点落在该矩形中 则需要重新挑选该方向的中心点–》第四点,否则该centerpoint 就是该方向的最合适的
- 如何挑选呢?在图像搜索起始点 search Start Point 到 search End Point 依次遍历的点pixel 作为其中心点
- 则新的矩形也通过threshold 建立起来,再次检测所有gtbox 的中心点是否落在矩形中,如果没有,则将其添加到我们的侯选集合,否则跳过改循环继续寻找。
- 在候选集合中点寻找最靠近图像中心的点,找到该点并返回
- 如果没有找到一个合适的候选点 则返回-1
3.2 代码如下:
def searchCenter(pointlist, neg_limit, pos_limit, centerPoint, dir, limit=10,debug=False):
'''
单方向 从负极限到正极限 搜索 中心点最适合点
Args:
pointlist: 搜索须满足的点集合
neg_limit: 负极限
pos_limit: 正极限
centerPoint: 中心点的值
dir: 方向 x :0 y:1
limit: 中心点的允许值
Returns: -1 没有找到合适的点
or
一个最合适点
'''
# 后选集
Candidate_list = []
num = len(pointlist)
if debug:
print(f"搜索范围 {neg_limit} : {pos_limit}")
for x_pixel in range(neg_limit, pos_limit):
temp = 0
neg_center_limit = x_pixel - limit
pos_center_limit = x_pixel + limit
stra = 'p: '
for point in pointlist:
stra += (' ' + str(point[dir]))
if point[dir] < neg_center_limit or point[dir] > pos_center_limit:
temp += 1
if temp == num:
# Shuo说明该pixel 符合要求
Candidate_list.append(x_pixel)
if debug:
print('*' * 50)
print(stra)
print(f'后选集添加:{x_pixel},判断负界限:{neg_center_limit},判断正界限:{pos_center_limit},temp:{temp},num:{num} \n')
print('*' * 50)
if len(Candidate_list) != 0:
# 所有的候选集 到中心点最近的一条线
Candinate_array = np.array(Candidate_list)
center = np.array([centerPoint])
tempArray = abs(Candinate_array - center)
# qiu丘处最小值的索引
minindex = np.argmin(tempArray, axis=0)
if debug:
print(f'所有的后选集:{Candinate_array}\n')
print(f'处理后的后选集:{tempArray}\n')
print(f'所有的后选集的最小值:{Candinate_array[minindex]}\n')
# fan返回最小值的索引对应的数
return Candinate_array[minindex]
else:
return -1
def demo_Brute_force_search(n=4 , width=100, height=100,debug=True):
# n = 4 # 生成几个点
# 随即生成n dian
randomPoingList = []
for i in range(n):
x, y = random.randint(0, width), random.randint(0, height)
randomPoingList.append((x, y))
if debug:
print(f'随即生成点为\n')
for i in range(len(randomPoingList)):
print(f'point{i}: {randomPoingList[i]} \n')
# 中心点 的坐标值 一般是图像w/2 h/2
cx, cy = width //2 , height // 2
# 限定距离阈值
limit = 10
l_center_limit = cx - limit
r_center_limit = cx + limit
u_center_limit = cy - limit
d_center_limit = cy + limit
l_limit = width // 3 # 左界限
r_limit = width // 3 * 2 # 右界限
u_limit = height // 3 # 上界限
d_limit = height // 3 * 2 # 下界限
if debug:
print(f'中心点的值: {cx}, {cy}\n'
f'允许阀值 {limit}\n')
print(f"水平允许范围 {l_center_limit} : {r_center_limit}\n ")
print(f"水平允许范围 {u_center_limit} : {d_center_limit}\n ")
print(f'搜索水平界限 {l_limit}:{r_limit} \n')
print(f'搜索垂直界限 {u_limit}:{d_limit} \n')
# 检测所有点是否符合需求
fitNums_x = 0
fitNums_y = 0
num = len(randomPoingList)
for point in randomPoingList:
if point[0] < l_center_limit or point[0] > r_center_limit:
fitNums_x += 1
if point[1] < u_center_limit or point[1] > d_center_limit:
fitNums_y += 1
if debug:
print(f'fitNums_x:{fitNums_x}')
print(f'fitNums_y:{fitNums_y}')
if fitNums_x != num:
if debug:
print(f'x 点不满足,当前点数: {fitNums_x} 需求数目: {num} 开始搜索模式:\n')
# 说明有点不满足 开始搜索模式
# 搜索模式: 重新调整中心点 在范围内不断重新调整中心点位置 -》 最合适的点 x中心点
x_pixel_centerPoint = searchCenter(randomPoingList, l_limit, r_limit, cx, 0, 10,debug)
if x_pixel_centerPoint == -1:
assert ValueError("can't find compitable point")
else:
x_pixel_centerPoint = cx
if fitNums_y != num:
if debug:
print(f'y 点不满足,当前点数: {fitNums_y} 需求数目: {num} 开始搜索模式:\n')
# 说明有点不满足 开始搜索模式
# 搜索模式: 重新调整中心点 在范围内不断重新调整中心点位置 -》 最合适的点 x中心点
y_pixel_centerPoint = searchCenter(randomPoingList, u_limit, d_limit, cy, 1, 10, debug)
if y_pixel_centerPoint == -1:
assert ValueError("can't find compitable point")
else:
y_pixel_centerPoint = cy
# 至此得到 最合适的中心点位置
return x_pixel_centerPoint, y_pixel_centerPoint
if __name__ == '__main__':
demox,demoy = demo_Brute_force_search(n=200,width=3000,height=2000,debug=False)
print(f'最合适的xy点:{demox},{demoy} j= {j}')
3.3 总结
3.3.1 上述的代码中:
n = 200 表示随即生成的 label 点
debug=False 是否是调试模式,调试模式下会打印中间 的值
搜索范围我限定在 图像的 1/3 到 2/3 这里
l_limit = width // 3 # 左界限
r_limit = width // 3 * 2 # 右界限
u_limit = height // 3 # 上界限
d_limit = height // 3 * 2 # 下界限
3.3.2 实验总结:
我大概实验了100次,随即的点数目在 200-1000 逐步往上涨,閾值=10,搜索范围在图像的 1/3 到 2/3 大概在 300 左右会出现找不到合适的中心值
最合适的xy点:1493,-1 j= 325
最合适的xy点:1575,-1 j= 355
最合适的xy点:1500,-1 j= 316
最合适的xy点:1509,-1 j= 357
最合适的xy点:1443,-1 j= 334
最合适的xy点:1518,-1 j= 330
最合适的xy点:1500,-1 j= 336
最合适的xy点:1525,-1 j= 320
最合适的xy点:1543,-1 j= 278
最合适的xy点:1537,-1 j= 288
最合适的xy点:1509,-1 j= 335
最合适的xy点:1523,-1 j= 388
最合适的xy点:1504,-1 j= 358
最合适的xy点:1500,-1 j= 317
最合适的xy点:1546,-1 j= 342
最合适的xy点:1498,-1 j= 282
最合适的xy点:1497,-1 j= 300
最合适的xy点:1565,-1 j= 305
最合适的xy点:1500,-1 j= 329
最合适的xy点:1490,-1 j= 300
最合适的xy点:1649,-1 j= 340
最合适的xy点:1526,-1 j= 346
最合适的xy点:1558,-1 j= 311
最合适的xy点:1500,-1 j= 345
最合适的xy点:1468,-1 j= 325
最合适的xy点:1444,-1 j= 297
最合适的xy点:1524,-1 j= 359
最合适的xy点:1487,-1 j= 271
最合适的xy点:1511,-1 j= 359
最合适的xy点:1503,-1 j= 293
最合适的xy点:1504,-1 j= 312
最合适的xy点:1571,-1 j= 310
最合适的xy点:1437,-1 j= 317
最合适的xy点:1526,-1 j= 338
最合适的xy点:1434,-1 j= 337
最合适的xy点:1520,-1 j= 334
最合适的xy点:1494,-1 j= 299
最合适的xy点:1534,-1 j= 333
最合适的xy点:1572,-1 j= 352
最合适的xy点:1496,-1 j= 290
最合适的xy点:1523,-1 j= 353
最合适的xy点:1419,-1 j= 305
最合适的xy点:1514,-1 j= 317
最合适的xy点:1496,-1 j= 340
最合适的xy点:1500,-1 j= 320
最合适的xy点:1495,-1 j= 346
最合适的xy点:1461,-1 j= 374
最合适的xy点:1441,-1 j= 307
最合适的xy点:1488,-1 j= 309
最合适的xy点:1523,-1 j= 308
最合适的xy点:1430,-1 j= 327
最合适的xy点:1480,-1 j= 294
最合适的xy点:1504,-1 j= 277
最合适的xy点:1500,-1 j= 315
最合适的xy点:1512,-1 j= 313
最合适的xy点:1530,-1 j= 375
最合适的xy点:1513,-1 j= 304
最合适的xy点:1545,-1 j= 347
最合适的xy点:1492,-1 j= 342
最合适的xy点:1481,-1 j= 363
最合适的xy点:1520,-1 j= 353
最合适的xy点:1472,-1 j= 346
最合适的xy点:1496,-1 j= 378
最合适的xy点:1447,-1 j= 306
最合适的xy点:1341,-1 j= 362
最合适的xy点:1532,-1 j= 318
最合适的xy点:1500,-1 j= 307
最合适的xy点:1469,-1 j= 306
最合适的xy点:1501,-1 j= 388
最合适的xy点:1497,-1 j= 281
最合适的xy点:1498,-1 j= 355
最合适的xy点:1471,-1 j= 308
最合适的xy点:1542,-1 j= 315
最合适的xy点:1554,-1 j= 300
最合适的xy点:1485,-1 j= 354
最合适的xy点:1441,-1 j= 335
最合适的xy点:1506,-1 j= 313
最合适的xy点:1493,-1 j= 319
最合适的xy点:1475,-1 j= 337
最合适的xy点:1551,-1 j= 307
最合适的xy点:1579,-1 j= 362
最合适的xy点:1475,-1 j= 320
最合适的xy点:1426,-1 j= 364
最合适的xy点:1507,-1 j= 313
最合适的xy点:1500,-1 j= 317
最合适的xy点:1508,-1 j= 335
最合适的xy点:1494,-1 j= 314
最合适的xy点:1585,-1 j= 274
最合适的xy点:1464,-1 j= 328
最合适的xy点:1508,-1 j= 249
最合适的xy点:1508,-1 j= 347
最合适的xy点:1500,-1 j= 331
最合适的xy点:1490,-1 j= 339
最合适的xy点:1500,-1 j= 345
最合适的xy点:1532,-1 j= 332
最合适的xy点:1513,-1 j= 328
最合适的xy点:1500,-1 j= 376
最合适的xy点:1588,-1 j= 306
最合适的xy点:1536,-1 j= 329
最合适的xy点:1451,-1 j= 361
Process finished with exit code 0