本文使用python+openCV
用到的算法:
高斯滤波
Canny边缘检测
ROI和mask
霍夫变换
离群值过滤
最小二乘法拟合
win+x选择运行,然后输入cmd
输入pip install opencv-python
等待安装
在IDLE中新建脚本.py文件,输入import cv2
,如果无报错即为安装成功。
再输入print(cv2.__version__)
可查看openCV版本。
cv2.imread(const String & filename, int flags = IMREAD_COLOR)
第一个参数是窗口的名字,第二个参数是读取格式(彩色或灰度),函数返回值是图片转换格式后所对应的列表。
如img = cv2.imread('img.jpg',cv2.IMREAD_GRAYSCALE)
cv2.imshow(window_name, img)
第一个参数是窗口的名字,可以创建多个窗口,但是必须给他们不同的名字。第二个参数是显示格式,可以是img图片格式,也可以是mat数组格式。
cv2.waitKey(int x)
相当于程序延时,调整
cv2.imshow()
的显示时间。延时时间为x毫秒。返回值为在延时期间按下键盘上按键所对应的ASCII值。
x=0时,即cv2.waitKey(0)
表示程序停在此处,直到手动关闭cv2.imshow()
的窗口。
例如设计一个,无穷延时,当键盘按下q
时退出。
if cv2.waitKey(1) & 0xFF == ord(‘q’): break
#ord()是将字符转换为ASCII码
cv2.imwrite(newfile_name, img)
第一个参数是保存的新图片的文件名,第二个参数是应保存的图片对应的列表。
cv2.destroyAllWindows()
关闭所有openCV打开的窗口。
CV2提供了提取图像边缘的函数canny。其算法思想如下:
1. 使用高斯模糊,去除噪音点(cv2.GaussianBlur)
2. 灰度转换(cv2.cvtColor)
3. 使用sobel算子,计算出每个点的梯度大小和梯度方向
4. 使用非极大值抑制(只有最大的保留),消除边缘检测带来的杂散效应
5. 应用双阈值,来确定真实和潜在的边缘
6. 通过抑制弱边缘来完成最终的边缘检测
gaussian = cv2.GaussianBlur(color_img, (gaussian_ksize,gaussian_ksize), gaussian_sigmax)
color_img 输入图片
gaussian_ksize 高斯核大小,可以为方形矩阵,也可以为矩形
gaussian_sigmax X方向上的高斯核标准偏差
没看太懂这个函数,目前仅局限于搬来直接用,下次一定
gray_img = cv2.cvtColor(input_image, flag)
用于颜色空间转换。input_image为需要转换的图片,flag为转换的类型,返回值为颜色空间转换后的图片矩阵。flag对应:
cv2.COLOR_BGR2GRAY BGR -> Gray
cv2.COLOR_BGR2RGB BGR -> RGB
cv2.COLOR_BGR2HSV BGR -> HSV
可以了解一下该函数和cv2.imread()的区别
edge_img = cv2.Canny(gray_img,canny_threshold1,canny_threshold2)
imag为所操作的图片,threshold1为下阈值,threshold2为上阈值,返回值为边缘图。
利用数组选取ROI(region of interest,感性趣的区域,然后与原图进行布尔运算(与运算)。
poly_pts = numpy.array([[[0,368],[300,210],[340,210],[640,368]]])
四个数组创建后保存在变量poly_pts中。
mask = np.zeros_like(gray_img)
构建一个与gray_img同维度的数组,并初始化所有变量为零。
cv2.fillPoly(mask, pts, color)
绘制多边形函数。mask为绘制对像,pts为绘制范围,color为绘制颜色。
img_mask = cv2.bitwise_and(gray_img, mask)
与运算
得到一系列的直线
lines = cv2.HoughLinesP(edge_img, 1, np.pi / 180, 15, minLineLength=40, maxLineGap=20)
edge_img: 要检测的图片矩阵
参数2: 距离r的精度,值越大,考虑越多的线
参数3: 距离theta的精度,值越大,考虑越多的线
参数4: 累加数阈值,值越小,考虑越多的线
minLineLength: 最短长度阈值,短于这个长度的线会被排除
maxLineGap:同一直线两点之间的最大距离
返回值::
[np.array([[x_1,y_1, x_2, y_2]]),
np.array([[x_1, y_1, x_2, y_2]]),
…,
np.array([[x_1, y_1, x_2, y_2]])]
循环查找超出设定范围的斜率,并去除。
idx = np.argmax(diff)
当diff中存放的是一维时,找到diff中最大的数值,并返回该值所在位置。
示例:
one_dim_array = np.array([1, 4, 5, 3, 7, 2, 6])
print(np.argmax(one_dim_array))
打印结果为 4
lines.pop(idx)
从列表lines中把第idx数去除
获得左车道线和右车道线的理想直线
x_coords = np.ravel([[line[0][0], line[0][2]] for line in lines])
将多维数组降为一维
还未想明白转换关系,下次一定
poly = np.polyfit(x, y, deg)
x, y为各个点的横纵坐标,deg为拟合曲线的次数
y_e = np.polyval(poly, x)
拟合曲线之后,x在曲线上对应的y值
cv2.line(img, tuple(line[0]), tuple(line[1]), color,thickness)
在图片上画线,img为所标注的目标图片,ine[0]为起点坐标,line[1]为终点坐标,thickness为线宽。
注意两个坐标需要为tuple元组格式,即tuple(line[0])
capture = cv2.VideoCapture('video.mp4')
如果为
cv2.VideoCapture(0)
,表示打开笔记本的内置摄像头。
ret, frame = capture.read()
其中ret是布尔值,如果读取帧是正确的则返回True,如果文件读取到结尾,它的返回值就为False。
frame就是每一帧的图像,是个三维矩阵。
fourcc = cv2.VideoWriter_fourcc('X', 'V', 'I', 'D')
fourcc意为四字符代码(Four-Character Codes),顾名思义,该编码由四个字符组成,下面是VideoWriter_fourcc对象一些常用的参数,注意:字符顺序不能弄混
cv2.VideoWriter_fourcc(‘I’, ‘4’, ‘2’, ‘0’),该参数是YUV编码类型,文件名后缀为.avi
cv2.VideoWriter_fourcc(‘P’, ‘I’, ‘M’, ‘I’),该参数是MPEG-1编码类型,文件名后缀为.avi
cv2.VideoWriter_fourcc(‘X’, ‘V’, ‘I’, ‘D’),该参数是MPEG-4编码类型,文件名后缀为.avi
cv2.VideoWriter_fourcc(‘T’, ‘H’, ‘E’, ‘O’),该参数是Ogg Vorbis,文件名后缀为.ogv
cv2.VideoWriter_fourcc(‘F’, ‘L’, ‘V’, ‘1’),该参数是Flash视频,文件名后缀为.flv
outfile = cv2.VideoWriter(filename, fourcc, 25, (1280,368))
filename为写入视频的文件名,fourcc为视频编码格式cv2.VideoWriter_fourcc()的返回值,25为帧率,(1280,368)为视频大小。
ret, frame = capture.read()
第一个参数ret 为布尔值即True 或者False,代表有没有读取到图片,第二个参数frame表示截取到一帧的图片
output = np.concatenate((origin, frame), axis=1)
能够一次完成多个数组的拼接
不写axis参数的话,默认为按列拼接;若axis = 1的话,即为按行拼接;
axis参数意义没搞太明白,下次一定
程序存在小bug但不影响检测视频生成,如果哪位大佬知道bug怎么解决记得踢我一脚。
cv2.imshow()
总是卡住无响应,无法自己关闭窗口,使用cv2.destroyAllWindows()
也还是卡住;
而且报告错误:
error: OpenCV(4.5.5) D:\a\opencv-python\opencv-python\opencv\modules\imgproc\src\smooth.dispatch.cpp:617: error: (-215:Assertion failed) !_src.empty() in function 'cv::GaussianBlur'
> 卡住的问题有人说是openCV对一部分硬件的适配不好,我比较在赞成这种观点。 报错 cv2.error error:
> (-215:Assertion failed) dst.data == (uchar*)dst_ptr in function
> 'cvShowImage'
>
> 同样的代码,我发现在公司电脑1060上,cv2.imshow()就可以显示,但在自己2080ti上就总是报错如上。于是锁定在cv2版本问题,果然卸掉最新的4.0版本,换上3.4.4.19就好了。
>
> 可能是4.0版本与2080ti的卡还不兼容。
> 来源:https://blog.csdn.net/qq_39938666/article/details/88179966
报错的问题目前未解决,也修改不掉。
完全实现对视频形式的单车道直线行驶时对车道线检测和标注。
import cv2
import numpy as np
#高斯滤波+canny边缘检测
def get_edge_img(color_img, gaussian_ksize=5, gaussian_sigmax=1,
canny_threshold1=50, canny_threshold2=100):
#param intoduction
#color_img 输入图片 gaussian_ksize 高斯核大小
#gaussian_sigmax X方向上的高斯核标准偏差
gaussian = cv2.GaussianBlur(color_img, (gaussian_ksize, gaussian_ksize),
gaussian_sigmax)
gray_img = cv2.cvtColor(gaussian,cv2.IMREAD_GRAYSCALE)
edge_img = cv2.Canny(gray_img,canny_threshold1,canny_threshold2);
return edge_img
def roi_mask(gray_img):
poly_pts = np.array([[[0,368],[300,210],[340,210],[640,368]]])
mask = np.zeros_like(gray_img)
cv2.fillPoly(mask, pts=poly_pts, color=255)
img_mask = cv2.bitwise_and(gray_img, mask)
return img_mask
def get_lines(edge_img):
#斜率计算
def calculate_slope(line):
x_1, y_1, x_2, y_2 = line[0]
slope = (y_2-y_1)/(x_2-x_1)
return slope
#离群值过滤
def reject_abnormal_lines(lines, threshold):
slopes = [calculate_slope(line) for line in lines]
while len(lines)>0:
mean = np.mean(slopes)
diff = [abs(s-mean) for s in slopes]
idx = np.argmax(diff)
if diff[idx]>threshold:
slopes.pop(idx)
lines.pop(idx)
else:
break
return lines
#最小二乘拟合
def least_squares_fit(lines):
x_coords = np.ravel([[line[0][0], line[0][2]] for line in lines])
y_coords = np.ravel([[line[0][1], line[0][3]] for line in lines])
# 2. 进行直线拟合.得到多项式系数
poly = np.polyfit(x_coords, y_coords, deg=1)
# 3. 根据多项式系数,计算两个直线上的点,用于唯一确定这条直线
point_min = (np.min(x_coords), np.polyval(poly, np.min(x_coords)))
point_max = (np.max(x_coords), np.polyval(poly, np.max(x_coords)))
return np.array([point_min, point_max],dtype=np.int0)
lines = cv2.HoughLinesP(edge_img, 1, np.pi/180, 15, minLineLength=40, maxLineGap=20)
left_lines = [line for line in lines if calculate_slope(line)<0]
right_lines = [line for line in lines if calculate_slope(line)>0]
left_lines = reject_abnormal_lines(left_lines, threshold=0.2)
right_lines = reject_abnormal_lines(right_lines, threshold=0.2)
return least_squares_fit(left_lines),least_squares_fit(right_lines)
def draw_line(img, lines):
left_line, right_line = lines
cv2.line(img, tuple(left_line[0]), tuple(left_line[1]), color=(0,255,255),thickness=5)
cv2.line(img, tuple(right_line[0]), tuple(right_line[1]), color=(0,255,255),thickness=5)
def show_lane(color_img):
edge_img = get_edge_img(color_img)
mask_gray_img = roi_mask(edge_img)
lines = get_lines(mask_gray_img)
draw_line(color_img, lines)
return color_img
if __name__ == '__main__':
capture = cv2.VideoCapture('video.mp4')
fourcc = cv2.VideoWriter_fourcc('X', 'V', 'I', 'D')
outfile = cv2.VideoWriter('output.avi', fourcc, 25, (1280,368))
while True:
ret, frame = capture.read()
origin = np.copy(frame)
frame = show_lane(frame)
output = np.concatenate((origin, frame), axis=1)
outfile.write(output)
cv2.imshow('video', output)
cv2.waitKey(10)
分步操作检测图片和检测视频的源码、测试图片和测试视频连接:https://download.csdn.net/download/qq_27839923/75831347
SeruTek K732D– 基于Kintex-7 325T的32通道高速TDC演示方案请搜索“瑟如电子”了解详情简介SeruTek K732D是上海瑟如电子科技基于KC705开发板制作的一款32通道TDC演示方案。K732D在单片K7325T上集成了33路时间戳单元、一个Microblaze微控制器、128KB Block SRAM、自校准模块、时间戳解析、时差计算模块以及用于测试的脉冲序列产生模块。K732D使用KC705开发板PL侧的200MHz差分时钟作为系统的主时钟;利用FMCvLPC扩展
C语言之所以被称为模块化语言,原因在于C语言的程序结构是由一个个的“模块”搭建起来的,这些所谓的模块就是函数,因此,函数是构成C程序的最基本的组件,我们的程序的功能可能很复杂,但是我们可以通过函数来分解,然后在组装它们,这种做法在遇到大规模软件工程之前,是非常主流的想法。在目前的软件开发中,也大量使用像C语言这样的模块化语言来描述问题,只不过当今世界,在面临大规模软件工程的开发时,面向对象语言也许
1.sessionid 的生成浏览器第一次跟服务器请求的时候,服务器会创建一个session(会话),并生成一个唯一的key(sessionid),把用户的一些信息,状态存在session里,并把sessionid和session当作key,value存起来(可以存在缓存里),然后服务器把sessionid以cookie的形式发送给浏览器,浏览器下次访问服务器时直接携带上cookie中的sess...
@[TOC] Bugly Android热更新问题解决[Android11,minSdkVersion=23]最近在使用Bugly Android热更新的时候遇到一些问题,在这里分享一些解决方案。Bugly Android热更新使用指南首先关于基本的集成步骤可以参考官方文档。下面主要讲一下需要改动注意的地方。注意事项Project下面的build.gradle需要一下改动:// Top-level build file where you can add configuration opti
用到的JAR包如下(可以直接到POI官网上下载也可以在文章的附件中下载):poi-3.9-20121203.jarpoi-ooxml-3.9-20121203.jarpoi-ooxml-schemas-3.9-20121203.jarxmlbeans-2.3.0.jar 可能有冲突的JAR包,如果工程lib中存在,需要删除。xbean-2.1.0.jar ...
起步本章介绍开始使用Git前的相关知识。我们会先了解一些版本控制工具的历史背景,然后试着让Git在你的系统上跑起来,直到最后配置好,可以正常开始开发工作。读完本章,你就会明白为什么Git会如此流行,为什么你应该立即开始使用它。版本控制什么是版本控制?我为什么要关心它呢?版本控制是一种记录一个或若干文件内容变化,以便将来查阅特定版本修订情况的系统。在本书所展示的例子中,我们仅对保存着软件
lda简介(后期补全理论部分)1、lda是一种无监督的贝叶斯模型:P(词 | 文档)=P(词 | 主题)P(主题 | 文档)同一主题下,某个词出现的概率,以及同一文档下,某个主题出现的概率,两个概率的乘积,可以得到某篇文档出现某个词的概率。2、lda用来推测文档的主题分布。它可以将文档集中每篇文档的主题以概率分布的形式给出,从而通过分析一些文档抽取出它们的主题分布后,便可以根据主题分布进行主题聚类或文本分类。3、lda 采用词袋模型。所谓词袋模型,是将一篇文档,我们仅考虑一个词汇是否出现,而不考虑
常用的SQLAlchemy查询过滤器过滤器说明filter()把过滤器添加到原查询上,返回一个新查询filter_by()把等值过滤器添加到原查询上,返回一个新查询limit使用指定的值限定原查询返回的结果offset()偏移原查询返回的结果,返回一个新查询order_by()根据指定条件对原...
内网安全监控和预警平台架构设想需求简介内网安全监控和预警平台是内网安全建设的物质基础,是所有甲方安全建设的必备武器库,无论是应急响应和追踪溯源,还是预知告警、自我清查;做下来总的体会是几个问题永远挥之不去,阴魂不散:资产不清(尤其是资产对应的负责人员和业务特点不明确)监控不全(对流量覆盖度不够,日志配置和收集不够,应急响应和追踪溯源的时候查不到、查不清、查一半等问题突出)探测不到...
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:aop="http://www.springfra
目录一、虚拟机测试环境搭建二、开发板挂载网络文件系统三、RS485测试附录本文档中利用交叉编译工具编译一个app程序用于测试RS485通信,需利用nfs挂载的形式该app下载至开发板中。一、虚拟机测试环境搭建安装NFS组件sudo apt-get install nfs-kernel-server建立共享文件夹mkdir /nfs设置共享目录修改虚拟机...
安装进入官网官网地址点击release版本链接或者直接点击这个链接地址点击下载解压出如下目录进入目录,启动服务[email protected] ~ % cd /Users/java0904/Downloads/[email protected] etcd-v3.5.1-darwin-amd64 % lltotal 153960drwxr-xr-x@ 12 java0904 sta