生长算法和巡中线算法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. class com.ttsx.activity.item.dao.entity.RoleMenu ,Not found @TableId annotation, Cannot use Mybatis-Plus 'xxById' Method. 报错解决办法

    启动项目的时候,有几条WARN警告,如图: 引起原因: 是因为数据表实体类 没有di导致的. 例如: 解决办法: 增加实体id字段!或可以忽略!不影响程序!

  2. mysql存储过程之循环遍历查询结果集

    mysql存储过程之循环遍历查询结果集 -- 创建存储过程之前需判断该存储过程是否已存在,若存在则删除 DROP PROCEDURE IF EXISTS init_reportUrl; -- 创建存储 ...

  3. php nginx 504 Gateway Timeout 网关超时错误

    对于 Nginx + FastCGI上的504网关超时错误(php-fpm),我们可以修改PHP和nginx的执行超时时间. 配置php 修改 php.ini(CentOS路径是/etc/php.in ...

  4. BigDecimal类--java进阶day05

    1.BigDecimal出现的原因 2.BigDecimal的创建 不推荐第一种形式,会有误差 第二种方式创建对象 第三种方式调用方法 2.BigDecimal常用方法 除法的特殊事项 如果有除不尽的 ...

  5. openGL库环境简单配置

    主要是针对openGL的一些初步的学习,因为openCV主要是处理图像视频,是从现有的得到数据,而openGL好像是从数据进行绘图,学习一下.在<计算机图形学编程>一书中,它把图形编程定性 ...

  6. 基于华为交换机的三层Clos架构(Leaf-Spine)配置指南

    基于华为交换机的三层Clos架构(Leaf-Spine)配置指南 目录 设计原则 配置步骤 物理连接与基础配置 路由协议配置 VXLAN+EVPN配置 M-LAG高可用配置 BFD快速检测 验证命令 ...

  7. JAVA 线程实现/创建方式

    每天记录一个知识点: 概要: java创建线程的方式: 继承Thread类 实现Runnable接口 通过Callable和Future创建线程 基于线程池的方式 java创建线程池的四种方式: ne ...

  8. Junit单元测试的Gradle设置

    官方文档 https://docs.gradle.org/current/userguide/java_testing.html test{ useJUnit() //指定使用junit执行测试. / ...

  9. 如何在 Go 中解析 yaml 文件

    Go 语言没有内置解析 yaml 文件的功能,实现 yaml 的解析可以使用第三方库 gopkg.in/yaml.v2 和 gopkg.in/yaml.v3. 下面以解析 config.yml 文件为 ...

  10. [笔记]PHP里类的申明和对象的实例化(笔记)

    1.申明类 class 类名{  //属性----------  public 属性 = 值:  public 属性:  //方法-----------  function 方法名($n1,$n2){ ...