生长算法和巡中线算法python实现代码示例(自用)

import cv2
import time
import numpy as np
from math import pi, isnan # PID算法类
class PID():
_kp = _ki = _kd = _integrator = _imax = 0
_last_error = _last_derivative = _last_t = 0
_RC = 1 / (2 * pi * 20) def __init__(self, p=0, i=0, d=0, imax=0):
self._kp = float(p)
self._ki = float(i)
self._kd = float(d)
self._imax = abs(imax)
self._last_derivative = float('nan') def get_pid(self, error, scaler):
tnow = int(round(time.time() * 1000))
dt = tnow - self._last_t
output = 0
if self._last_t == 0 or dt > 1000:
dt = 0
self.reset_I()
self._last_t = tnow
delta_time = float(dt) / float(1000)
output += error * self._kp
if abs(self._kd) > 0 and dt > 0:
if isnan(self._last_derivative):
derivative = 0
self._last_derivative = 0
else:
derivative = (error - self._last_error) / delta_time
derivative = self._last_derivative + \
((delta_time / (self._RC + delta_time)) *
(derivative - self._last_derivative))
self._last_error = error
self._last_derivative = derivative
output += self._kd * derivative
output *= scaler
if abs(self._ki) > 0 and dt > 0:
self._integrator += (error * self._ki) * scaler * delta_time
if self._integrator < -self._imax:
self._integrator = -self._imax
elif self._integrator > self._imax:
self._integrator = self._imax
output += self._integrator
return output def reset_I(self):
self._integrator = 0
self._last_derivative = float('nan') class RobotControl():
def __init__(self):
# PID调参的地方
self.rho_pid = PID(p=0.4, i=0)
self.theta_pid = PID(p=0.001, i=0)
# 图像大小处理
self.h = 0 # 480
self.w = 0 # 640
self.middle_line_x = 0
# 存中线坐标
self.middle_line_list = []
# 生长算法初始点
self.first_dot = (0, 0) def skip_image(self, cap, num):
for i in range(num):
_, frame = cap.read() def img_dispose(self, cap):
_, frame = cap.read()
frame = cv2.GaussianBlur(frame, (3, 3), 1)
# 灰度
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# 二值化
frame = cv2.adaptiveThreshold(frame, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 25, 5)
# retval, frame = cv2.threshold(frame, 127, 255, cv2.THRESH_BINARY_INV)
# kernel = np.ones((3, 3), np.uint8)
# img = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)
# 边界提取
# img1 = cv2.Canny(img, 80, 150, (5, 5))
# img = cv2.Canny(img, 80, 150, (3, 3))
# img = np.concatenate((frame, img), axis=1)
# img = np.hstack((img1, img2))
return frame def find_middle_line(self, frame):
# print(len(frame[0]))
point_size = 1
point_color = (127, 127, 127) # BGR
thickness = 4 # 可以为 0 、4、8
left_line = []
right_line = []
countall = 0
count = 0
# middle_dot = []
for i in range(self.h):
# 找左边
for j in range(int(self.middle_line_x), 0, -1):
if frame[i][j - 1] == 0:
left_line.append((i, j - 1))
break
else:
left_line.append((i, -1))
# 找右边
for j in range(int(self.middle_line_x), self.w):
if frame[i][j] == 0:
right_line.append((i, j))
break
else:
right_line.append((i, -1))
for i in range(self.h):
if left_line[i][1] != -1 and right_line[i][1] != -1:
# middle_dot.append((i, (left_line[i][1]+right_line[i][1])//2))
count += 1
a = (left_line[i][1] + right_line[i][1]) // 2
countall += a
cv2.circle(frame, (a, i), point_size, point_color, thickness)
if count != 0:
self.middle_line_x = countall // count # 更新赛道中线的位置
return frame # 生长算法
def grow_line(self, img, mode, begin_dot=(-1, -1)):
"""
:param img: 传入的图片
:param left_dot: 左边开始找的初始点
:param right_dot: 右边开始找的初始点
:param mode: 0 1 o代表找左边, 1代表找右边
:return: 返回找的线的元组列表
"""
dot_dic = {} def road_true(dot, mode, num, fx, fy):
"""
:param dot: 开始的点
:param mode: 当前情况下查点的模式
:param num: 希望查的点的个数
:param fx: 查横的方向
:param fy: 查竖的方向
:return: 返回是否合法
"""
if fx == 0 and fy == 0:
return -1
elif fx == 1 and fy == 1:
if mode == 0: # 向左
if dot[0] - num >= 0 and dot[1] - num >= 0:
return 1
else:
return 0
else: # 向右
if dot[0] + num < self.w - 1 and dot[1] - num >= 0:
return 1
else:
return 0
elif fx == 1:
if mode == 0:
if dot[0] - num >= 0:
return 1
else:
return 0
else:
if dot[0] + num < self.w - 1:
return 1
else:
return 0
elif fy == 1:
if mode == 0:
if dot[1] - num >= 0:
return 1
else:
return 0
else:
if dot[1] - num >= 0:
return 1
else:
return 0 # 先假设路是白色255, 边界是黑色0
road = 255
middle_road = 127
borad = 0 if begin_dot[0] != -1:
current_dot = begin_dot # current_dot[1]为y, current_dot[0]为x
if mode == 0: # 向左找
while 1:
if road_true(current_dot, mode, 1, fx=1, fy=0) and road_true(current_dot, mode, 1, fx=0, fy=1):
if (img[current_dot[1]][current_dot[0]] == road or img[current_dot[1]][
current_dot[0]] == middle_road) and img[current_dot[1]][current_dot[0] - 1] == borad:
dot_dic[current_dot[1]] = current_dot[0]
if current_dot[1] <= 0:
break
else:
current_dot = (current_dot[0], current_dot[1] - 1)
elif img[current_dot[1]][current_dot[0]] == borad:
current_dot = (current_dot[0] + 1, current_dot[1])
elif img[current_dot[1]][current_dot[0]] == road or img[current_dot[1]][
current_dot[0]] == middle_road:
current_dot = (current_dot[0] - 1, current_dot[1])
elif road_true(current_dot, mode, 1, fx=0, fy=1):
current_dot = (begin_dot[0], current_dot[1] - 1)
else:
break else: # 向右找
while 1:
if road_true(current_dot, mode, 1, fx=1, fy=0) and road_true(current_dot, mode, 1, fx=0, fy=1):
if (img[current_dot[1]][current_dot[0]] == road or img[current_dot[1]][
current_dot[0]] == middle_road) and img[current_dot[1]][current_dot[0] + 1] == borad:
dot_dic[current_dot[1]] = current_dot[0]
if current_dot[1] <= 0:
break
else:
current_dot = (current_dot[0], current_dot[1] - 1)
elif img[current_dot[1]][current_dot[0]] == borad:
current_dot = (current_dot[0] - 1, current_dot[1])
elif img[current_dot[1]][current_dot[0]] == road or img[current_dot[1]][
current_dot[0]] == middle_road:
current_dot = (current_dot[0] + 1, current_dot[1])
elif road_true(current_dot, mode, 1, fx=0, fy=1):
current_dot = (begin_dot[0], current_dot[1] - 1)
else:
break return img, dot_dic def run(self):
cap = cv2.VideoCapture(0)
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 160)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 120)
self.skip_image(cap, 30)
_, frame = cap.read()
self.w, self.h = frame.shape[1], frame.shape[0]
# 输出当前的图片大小
print(self.w, self.h)
self.middle_line_x = self.w // 2
left_first_dot = (self.middle_line_x, self.h - 1)
right_first_dot = (self.middle_line_x, self.h - 1)
self.first_dot = (self.middle_line_x, self.h - 1)
while 1:
try:
flag = 1
# 返回处理过的黑白图像
frame = self.img_dispose(cap)
# 找中线并更新数据
frame, dot_dic1 = self.grow_line(frame, 0, left_first_dot)
frame, dot_dic2 = self.grow_line(frame, 1, right_first_dot)
# print(dot_dic1, dot_dic2)
for i in range(self.h + 1):
if dot_dic1.get(i, -1) != -1 and dot_dic2.get(i, -1) != -1:
frame[i][(dot_dic1.get(i, -1) + dot_dic2.get(i, -1)) // 2] = 127
# 更新起始点
for i in range(self.h - 1, self.h - 12, -5):
if dot_dic1.get(i, -1) != -1 and dot_dic2.get(i, -1) != -1:
left_first_dot = (dot_dic1.get(i, -1) + 5, self.h - 1)
right_first_dot = (dot_dic2.get(i, -1) - 5, self.h - 1)
break
else:
left_first_dot = self.first_dot
right_first_dot = self.first_dot
cv2.imshow("1", frame)
command = cv2.waitKey(1) & 0xFF
if command == ord('q'):
break
except Exception as e:
print(e)
cv2.imshow("1", frame) if __name__ == '__main__':
robot = RobotControl()
robot.run()

生长算法和巡中线算法python实现代码示例(自用)的更多相关文章

  1. python 快速排序-代码示例

    def quick_sort(alist, first, last): if first >= last: # 如果开始等于结尾,即就一个元素 return mid_value = alist[ ...

  2. 建模分析之机器学习算法(附python&R代码)

    0序 随着移动互联和大数据的拓展越发觉得算法以及模型在设计和开发中的重要性.不管是现在接触比较多的安全产品还是大互联网公司经常提到的人工智能产品(甚至人类2045的的智能拐点时代).都基于算法及建模来 ...

  3. 几种排序算法的学习,利用Python和C实现

    之前学过的都忘了,也没好好做过总结,现在总结一下. 时间复杂度和空间复杂度的概念: 1.空间复杂度:是程序运行所以需要的额外消耗存储空间,一般的递归算法就要有o(n)的空间复杂度了,简单说就是递归集算 ...

  4. Python实现各种排序算法的代码示例总结

    Python实现各种排序算法的代码示例总结 作者:Donald Knuth 字体:[增加 减小] 类型:转载 时间:2015-12-11我要评论 这篇文章主要介绍了Python实现各种排序算法的代码示 ...

  5. Python使用DDA算法和中点Bresenham算法画直线

    title: "Python使用DDA算法和中点Bresenham算法画直线" date: 2018-06-11T19:28:02+08:00 tags: ["图形学&q ...

  6. 10 种机器学习算法的要点(附 Python 和 R 代码)

    本文由 伯乐在线 - Agatha 翻译,唐尤华 校稿.未经许可,禁止转载!英文出处:SUNIL RAY.欢迎加入翻译组. 前言 谷歌董事长施密特曾说过:虽然谷歌的无人驾驶汽车和机器人受到了许多媒体关 ...

  7. 10 种机器学习算法的要点(附 Python)(转载)

    一.前言 谷歌董事长施密特曾说过:虽然谷歌的无人驾驶汽车和机器人受到了许多媒体关注,但是这家公司真正的未来在于机器学习,一种让计算机更聪明.更个性化的技术 也许我们生活在人类历史上最关键的时期:从使用 ...

  8. 《机器学习实战》基于朴素贝叶斯分类算法构建文本分类器的Python实现

    ============================================================================================ <机器学 ...

  9. 【机器学习】【条件随机场CRF-2】CRF的预测算法之维特比算法(viterbi alg) 详解 + 示例讲解 + Python实现

    1.CRF的预测算法条件随机场的预测算法是给定条件随机场P(Y|X)和输入序列(观测序列)x,求条件概率最大的输出序列(标记序列)y*,即对观测序列进行标注.条件随机场的预测算法是著名的维特比算法(V ...

  10. HMM-前向后向算法理解与实现(python)

    目录 基本要素 HMM三大问题 概率计算问题 前向算法 后向算法 前向-后向算法 基本要素 状态 \(N\)个 状态序列 \(S = s_1,s_2,...\) 观测序列 \(O=O_1,O_2,.. ...

随机推荐

  1. Web前端入门第 12 问:HTML 常用属性一览

    HELLO,这里是大熊学习前端开发的入门笔记. 本系列笔记基于 windows 系统. HTML 常用属性大约 70 个,是否又头大了?脸上笑嘻嘻,心里嘛...嘿嘿... 温馨提示:属性不用死记硬背, ...

  2. Web前端入门第2问:前端开发是什么?与后端、全栈的区别是什么?一个完整的Web项目有哪些角色参与?

    一个完整的Web项目有哪些角色参与? 提出需求(这一步可以是甲方,也可以是用户) 需求分析,画出原型图(产品经理) 根据原型图输出 UI 界面及交互图(UI/UX设计师) 根据UI及交互效果画出页面, ...

  3. Vim编辑windows格式文件出现的[noeol][dos]的含义、解决方法及方法解释

    文章目录 前言 [dos] [noeol] 前言 最近想要将保存再windows的文件传到linux上,传进去保存文件之后,用vim打开发现在文件的底下出现了[dos] [noeol]这两个标志.然后 ...

  4. React.memo 解决函数组件重复渲染

    为什么会存在重复渲染? react 在 v16.8 版本引入了全新的 api,叫做 React Hooks,它的使用与以往基于 class component 的组件用法非常的不一样,不再是基于类,而 ...

  5. Centos下安装php mysql pdo以及gd扩展

    pdo扩展安装: yum install php-pdo pdomysql扩展安装: yum install php-pdo_mysql gd库扩展安装: yum install php-gd 安装后 ...

  6. Major、Minor、Build Number及Revision 版本号注解含义

    版本号 版本号由二至四个部分组成:主版本号.次版本号.内部版本号和修订号. 主版本号和次版本号两个部分为必选,内部版本号和修订号两个部分为可选.只有在未定义内部版本号部分时,修订号部分才为可选.所有定 ...

  7. phpstudy安装redis扩展 windows安装redis扩展

    1.首先查看自己本地环境的php版本信息: 执行phpinfo(),显示php相关信息 2.下载所需的扩展 php redis扩展下载地址 windows上,php开启扩展需要下载ddl 这里要注意的 ...

  8. 编写你的第一个 Django 应用程序,第7部分

    本教程从教程 6 停止的地方开始.我们将继续使用网络投票应用程序,并将专注于自定义 Django 自动生成的管理站点,这是我们在教程 2 中首次探索的. 一.自定义管理表单 通过用 admin.sit ...

  9. 在Proxmox VE pve中安装windows操作系统——以ltsc2019为例

    pve创建ltsc2019还是比较简单的.只是没有virtio驱动的话,选择磁盘的时候找不到磁盘.这里主要是列出如何加载virtio驱动 1.创建虚拟机忽略.注意需要新建2个CDROM.一个为wind ...

  10. 一步一步教你部署ktransformers,大内存单显卡用上Deepseek-R1

    环境准备 硬件环境 CPU:intel四代至强及以上,AMD参考同时期产品 内存:800GB以上,内存性能越强越好,建议DDR5起步 显卡:Nvidia显卡,单卡显存至少24GB(用T4-16GB显卡 ...