博主学习python做的第二个小项目,blog用以记录学习过程
任务要求:
1、调取NVIDIA NX系统摄像头,获取视频(帧)流
2、四种滤波分别采用:Canny、Sobel、Laplacian、Scharr
3、多进程(threading)
一、调取摄像头获取视频帧
详见上一篇blog:blog链接
二、四种滤波
-
Sobel滤波和Scharr滤波
两种滤波器本质上是同一种,Scharr滤波器是Sobel滤波器的特殊情况,具体描述见下图
代码如下:
#sobel滤波
sobelx = cv2.Sobel(gray, cv2.CV_64F, 1, 0)
sobely = cv2.Sobel(gray, cv2.CV_64F, 0, 1)
#在进行滤波时需要将数据类型从uint8转换为更高的CV_64F,内核矩阵即ksize默认为3
sobelx = numpy.uint8(numpy.absolute(sobelx))
sobely = numpy.uint8(numpy.absolute(sobely))
#滤波完成后需要将图片转换为能够哦显示的uint8
sobelcombine = cv2.bitwise_or(sobelx,sobely)
#对两幅分别在x和y方向进行求导的图片数据进行或操作叠加
#scharr滤波
scharr_x = cv2.Sobel(gray,cv2.CV_64F, 1, 0, ksize = -1)
scharr_y = cv2.Sobel(gray,cv2.CV_64F, 0, 1, ksize = -1)
#可以看到另sobel函数中的ksize = -1便可以为scharr函数
scharrcombine = cv2.addWeighted(scharr_x, 0.5, scharr_y, 0.5, 0)
#这里采用addWeight()函数进行
#scharrcombine = cv2.bitwise_or(scharr_x,scharr_y)
scharrcombine = cv2.convertScaleAbs(scharrcombine)
#这里采用convertScaleAbs()函数对叠加后的图片进行强制类型转换,以便后续采用imshow函数进行显示
-
Laplacian滤波
lapci = cv2.Laplacian(gray,cv2.CV_64F,ksize=3)
lapci = cv2.convertScaleAbs(lapci)
Laplacian,Sobel对同一张图片进行的滤波效果如下图:
-
Canny滤波
核心为两个阈值:
代码:
#Canny滤波
canny = cv2.Canny(gray,50,100)
#gray为灰度化后的图像
三、多线程处理
推荐b站莫烦的python多线程教程,链接:莫烦python,Threading学会多线程
另外这位博主对莫烦的内容进行了一定的整理,参见:多线程blog链接
小项目所有代码如下:
import threading
import cv2
import numpy
from queue import Queue
def T1_job(gary,q):
print("T1 start")
canny = cv2.Canny(gray,50,100)
print("T1 finish")
q.put(canny)
def T2_job(gray,q):
print("T2 start")
sobelx = cv2.Sobel(gray, cv2.CV_64F, 1, 0)
sobely = cv2.Sobel(gray, cv2.CV_64F, 0, 1)
sobelx = numpy.uint8(numpy.absolute(sobelx))
sobely = numpy.uint8(numpy.absolute(sobely))
sobelcombine = cv2.bitwise_or(sobelx,sobely)
#gray = sobekcombine
print("T2 finish")
q.put(sobelcombine)
def T3_job(gray,q):
print("T3 start")
scharr_x = cv2.Sobel(gray,cv2.CV_64F, 1, 0, ksize = -1)
scharr_y = cv2.Sobel(gray,cv2.CV_64F, 0, 1, ksize = -1)
scharrcombine = cv2.addWeighted(scharr_x, 0.5, scharr_y, 0.5, 0)
#scharrcombine = cv2.bitwise_or(scharr_x,scharr_y)
scharrcombine = cv2.convertScaleAbs(scharrcombine)
print("T3 finish")
q.put(scharrcombine)
def T4_job(gray,q):
print("T4 start")
lapci = cv2.Laplacian(gray,cv2.CV_64F,ksize=3)
lapci = cv2.convertScaleAbs(lapci)
# gray = lapci
print("T4 finish")
q.put(lapci)
cap = cv2.VideoCapture(0)
while(1):
# get a frame
ret, frame = cap.read()
#ret表示返回的布尔值,frame是返回的图像帧,read表示读取帧
# show a frame
# cv2.namedWindow("cpature",cv2.WINDOW_NORMAL)
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
q =Queue() # #q中存放返回值,代替return的返回值
threads = []
thread_1 = threading.Thread(target = T1_job,args=(gray,q))
thread_2 = threading.Thread(target = T2_job,args=(gray,q))
thread_3 = threading.Thread(target = T3_job,args=(gray,q))
thread_4 = threading.Thread(target = T4_job,args=(gray,q))
threads.append(thread_1)
threads.append(thread_2)
threads.append(thread_3)
threads.append(thread_4)
for thread in threads:
thread.start()
for thread in threads:
thread.join()
results = []
for _ in range(4):
results.append(q.get())#q.get()按顺序从q中拿出一个值
cv2.imshow("capture0",results[0])
cv2.imshow("capture1",results[1])
cv2.imshow("capture2",results[2])
cv2.imshow("capture3",results[3])
if cv2.waitKey(1) & 0xFF == ord('q'):
#waitKey("时间")表示延迟多少ms
#这里&为与运算符号,一般都用$$,效率更高
break
#循环只有在对程序框按下q并且延时1ms后才会中断
cap.release()
cv2.destroyAllWindows()
#最后关闭窗口是一个好习惯
这篇blog写的比较仓促,后续会更新更多细节以及优化代码,代码仅仅达到了能跑结果正确的程度,还需要进行优化,仅供参考。
本文截图的内容来自书籍:《OpenCV-Python-Tutorial-中文版》,可入qq群783462347文件区下载以及python的学习交流,一个兴趣使然的群,均为免费~