生长算法和巡中线算法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. linux npm 全局安装 command not found

    前言 在 linux 使用 npm 全局安装一个模块时,会提示命令找不到. 例如:npm install @quasar/cli -g 后 $ quasar -v quasar: command no ...

  2. Oralcle11.2.0.1.0使用出现的问题

    问题1:oracle中监听程序当前无法识别连接描述符中请求服务 解决方法1: 查看oracle的服务是否开启,计算机->管理->服务和应用程序->服务,如下图 解决方法2: 找到or ...

  3. oracle修改用户密码的方法

    Oracle用户名及默认密码 修改oracle用户的密码有以下方法: 普通用户 (1)通过alter user语法来进行修改 ,这也是最常见的方式: (2) 第二种方式,是通过password命令来修 ...

  4. VMware虚拟化的CPU调度原理及实践建议

    简介: ESXi的CPU调度原理及实践建议 ESXi的CPU调度原理 CPU调度器的设计目标 公平性:确保虚机按照各自配置的份额占用物理CPU.吞吐量:最大化物理CPU的使用率.响应性:vCPU从'就 ...

  5. Linux下使用fdisk扩大分区容量

    磁盘容量有300GB,之前分区的时候只分了一个150GB的/data分区,现在/data分区已经不够用了. 需求:把这块磁盘剩余的150GB容量增加到之前的/data分区,并且保证/data分区原有的 ...

  6. nginx下增加https端口的方法

    一.进入根目录我是使用xshell进行远程连接服务器的,连接到服务器首先输入cd /进入到根目录在这里插入图片描述二.配置nginx.conf文件首先输入cd etc/nginx进入到nginx目录在 ...

  7. delphi获得唯一ID字符串

    //这是我三层开发中常用的一个函数,直接调用CreateSortID uses System.Win.ComObj,System.RegularExpressions,System.StrUtils, ...

  8. python练习-爬虫(续)

    流程: 1 设置url 2 设置消息头 3 设置消息体 4 获取响应 5 解析相应 6 验证数据 接下来就是查询数据了. # 识别图片中的文字 #image = Image.open('captcha ...

  9. 【Guava】并发编程ListenableFuture&Service

    MoreExecutors directExecutor ExecutorService executor = Executors.newSingleThreadExecutor(); Settabl ...

  10. Python 潮流周刊#96:MCP 到底是什么?(摘要)

    本周刊由 Python猫 出品,精心筛选国内外的 250+ 信息源,为你挑选最值得分享的文章.教程.开源项目.软件工具.播客和视频.热门话题等内容.愿景:帮助所有读者精进 Python 技术,并增长职 ...