V4:
import cv2 as cv
import os
import numpy as npimport time# 遍历文件夹函数
def getFileList(dir, Filelist, ext=None):"""获取文件夹及其子文件夹中文件列表输入 dir:文件夹根目录输入 ext: 扩展名返回: 文件路径列表"""newDir = dirif os.path.isfile(dir):if ext is None:Filelist.append(dir)else:if ext in dir[-3:]:Filelist.append(dir)elif os.path.isdir(dir):for s in os.listdir(dir):newDir = os.path.join(dir, s)getFileList(newDir, Filelist, ext)return Filelistdef mid(follow, mask):crossroads = FalsehalfWidth = follow.shape[1] // 2half = halfWidth # 从下往上扫描赛道,最下端取图片中线为分割线for y in range(follow.shape[0] - 1, -1, -1):# V2改动:加入分割线左右各半张图片的宽度作为约束,减小邻近赛道的干扰if (mask[y][max(0, half - halfWidth):half] == np.zeros_like(mask[y][max(0, half - halfWidth):half])).all(): # 分割线左端无赛道left = max(0, half - halfWidth) # 取图片左边界else:left = np.average(np.where(mask[y][0:half] == 255)) # 计算分割线左端平均位置if (mask[y][half:min(follow.shape[1], half + halfWidth)] == np.zeros_like(mask[y][half:min(follow.shape[1], half + halfWidth)])).all(): # 分割线右端无赛道right = min(follow.shape[1], half + halfWidth) # 取图片右边界else:right = np.average(np.where(mask[y][half:follow.shape[1]] == 255)) + half # 计算分割线右端平均位置mid = (left + right) // 2 # 计算拟合中点vibra = abs(mid - half) # 振荡偏差# V3改动:检测到异常振荡则判定为十字路口,并保持直行# V4改动:设置了检测异常振荡的纵轴位置范围if vibra > int((30 / 640) * follow.shape[1]) and int((430 / 480) * follow.shape[0]) and y > int((50 / 480) * follow.shape[0]):crossroads = Truemid = int(mid)half = mid # 递归,从下往上确定分割线follow[y, mid] = 255 # 画出拟合中线if y == int((360 / 480) * follow.shape[0]): # 设置指定提取中点的纵轴位置mid_output = midif crossroads:# print("crossroads!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")mid_output = halfWidth# cv.circle(follow, (mid_output, 360), 5, 255, -1) # opencv为(x,y),画出指定提取中点error = follow.shape[1] // 2 - mid_output # 计算图片中点与指定提取中点的误差return follow, error # error为正数右转,为负数左转n = -1
# 存放图片的文件夹路径
path = "./crossroads20230802"
imglist = getFileList(path, [])
for imgpath in imglist:n += 1if n < 0:continue# V4改动:加入测量处理时间功能start_time = time.time()img = cv.imread(imgpath)img = cv.resize(img, (50, 50))# HSV阈值分割img_hsv = cv.cvtColor(img, cv.COLOR_BGR2HSV)mask = cv.inRange(img_hsv, np.array([43, 60, 90]), np.array([62, 255, 255]))follow = mask.copy()# follow, error = mid(follow, mask)_, error = mid(follow, mask)# print(n, f"error:{error}")end_time = time.time()print(end_time - start_time)
# cv.imshow("img", img)
# cv.imshow("mask", mask)
# cv.imshow("follow", follow)
# cv.waitKey(0)
#
# cv.destroyAllWindows()
V5:
import cv2 as cv
import os
import numpy as npimport time# 遍历文件夹函数
def getFileList(dir, Filelist, ext=None):"""获取文件夹及其子文件夹中文件列表输入 dir:文件夹根目录输入 ext: 扩展名返回: 文件路径列表"""newDir = dirif os.path.isfile(dir):if ext is None:Filelist.append(dir)else:if ext in dir[-3:]:Filelist.append(dir)elif os.path.isdir(dir):for s in os.listdir(dir):newDir = os.path.join(dir, s)getFileList(newDir, Filelist, ext)return Filelistdef mid(follow, mask):crossroads = FalsehalfWidth = follow.shape[1] // 2half = halfWidth # 从下往上扫描赛道,最下端取图片中线为分割线for y in range(follow.shape[0] - 1, -1, -1):# V5改动:减少重复计算,提高性能maximum = max(0, half - halfWidth)minimum = min(follow.shape[1], half + halfWidth)# V2改动:加入分割线左右各半张图片的宽度作为约束,减小邻近赛道的干扰if (mask[y][maximum:half] == np.zeros_like(mask[y][maximum:half])).all(): # 分割线左端无赛道left = maximum # 取图片左边界else:left = np.average(np.where(mask[y][0:half] == 255)) # 计算分割线左端平均位置if (mask[y][half:minimum] == np.zeros_like(mask[y][half:minimum])).all(): # 分割线右端无赛道right = minimum # 取图片右边界else:right = np.average(np.where(mask[y][half:follow.shape[1]] == 255)) + half # 计算分割线右端平均位置mid = (left + right) // 2 # 计算拟合中点vibra = abs(mid - half) # 振荡偏差# V3改动:检测到异常振荡则判定为十字路口,并保持直行# V4改动:设置了检测异常振荡的纵轴位置范围if vibra > int((30 / 640) * follow.shape[1]) and int((430 / 480) * follow.shape[0]) and y > int((50 / 480) * follow.shape[0]):crossroads = Truemid = int(mid)half = mid # 递归,从下往上确定分割线# follow[y, mid] = 255 # 画出拟合中线,实际使用时为提高性能可省略if y == int((360 / 480) * follow.shape[0]): # 设置指定提取中点的纵轴位置mid_output = midif crossroads:# print("crossroads!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")mid_output = halfWidth# cv.circle(follow, (mid_output, 360), 5, 255, -1) # opencv为(x,y),画出指定提取中点error = follow.shape[1] // 2 - mid_output # 计算图片中点与指定提取中点的误差return follow, error # error为正数右转,为负数左转n = -1
# 存放图片的文件夹路径
path = "./crossroads20230802"
imglist = getFileList(path, [])
for imgpath in imglist:n += 1if n < 0:continue# V4改动:加入测量处理时间功能start_time = time.time()img = cv.imread(imgpath)img = cv.resize(img, (100, 100))# HSV阈值分割img_hsv = cv.cvtColor(img, cv.COLOR_BGR2HSV)mask = cv.inRange(img_hsv, np.array([43, 60, 90]), np.array([62, 255, 255]))follow = mask.copy()# follow, error = mid(follow, mask)_, error = mid(follow, mask)# print(n, f"error:{error}")end_time = time.time()print(end_time - start_time)# cv.imshow("img", img)# cv.imshow("mask", mask)# cv.imshow("follow", follow)# cv.waitKey(0)
#
# cv.destroyAllWindows()