当前位置:   article > 正文

opencv入门使用_opencv使用

opencv使用

Opencv入门使用

学习国外视频之后手打的教程,若有不对的地方请留言==

1.显示图片

import cv2

img = cv2.imread("./resources/KS.jpg")
//窗口名称, 图片对象
cv2.imshow('Output', img)
//图片永久停留, n*1000: 停留n秒后消失
cv2.waitKey(0)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

效果
在这里插入图片描述

2.显示视频

cap = cv2.VideoCapture("./resources/twilight.mp4")

#设置循环,读取视频=读取每一帧图片
while True:
    success, img = cap.read()
    cv2.imshow("Video", img)
    //视频持续播放,如果按s键(设定的字母用小写),视频关闭
    if cv2.waitKey(1) & 0xFF == ord('s'):
        break
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

效果
在这里插入图片描述

3.启用摄像头

//0表示使用的摄像头,有1个摄像头就填入0
cap = cv2.VideoCapture(0)
//3代表宽度项,640为设置的宽度值
cap.set(3, 640)
//4代表高度项,480为设置的高度值
cap.set(4, 480)
//10代表亮度项, 100为设置的亮度
cap.set(10, 100)

while True:
    success, img = cap.read()
    cv2.imshow("Video", img)
    //摄像头持续开着,如果按s键(设定的字母用小写),摄像头关闭
    if cv2.waitKey(1) & 0xFF == ord('s'):
        break
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

效果
我就不露镜了

4.原图–>灰度图

img = cv2.imread("resources/KS.jpg")
//使用cvtColor功能,把彩图img的通道BGR转到GRAY(opencv中彩图通道顺序是BGR)
imgGray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
//窗口名称,显示的图片
cv2.imshow('Gray Image', imgGray)
cv2.waitKey(0)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

效果
在这里插入图片描述

5.原图–>灰度图–>高斯模糊图

img = cv2.imread("resources/KS.jpg")
imgGray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
//(blur1,blur2)是高斯核的大小,选取一般是奇数,模糊度和数字大小成正比
//进行滤波的图像的长宽比如果为1:1,那么选取blur时,一般设置blur1=blur2
//如果要进行滤波的图像的长宽比大致为m:n,那么选取blur时,尽量是blur1:blur2=m:n
//sigmaX – X方向上的高斯核标准偏差
imgBlur = cv2.GaussianBlur(imgGray, (3, 5), sigmaX=0)
cv2.imshow('Blur Image', imgBlur)
cv2.waitKey(0)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

效果
在这里插入图片描述

6.原图–>边缘图

img = cv2.imread("resources/KS.jpg")
//两个阈值越大,轮廓线条越少
imgCanny = cv2.Canny(img, 200, 250) 
cv2.imshow('Canny Image', imgCanny)
cv2.waitKey(0)
  • 1
  • 2
  • 3
  • 4
  • 5

效果
在这里插入图片描述

7.原图–>边缘图–>膨胀图

img = cv2.imread("resources/KS.jpg")
imgCanny = cv2.Canny(img, 200, 250)
//kernel是滑动窗口,在图像上进行从左到右,从上到下的平移,如果方框中存在白色,那么这个方框内所有的颜色都是白色
//uint8,表示变量是无符号整数,范围是0到255
//uint8是指0~2^8-1 = 255数据类型
kernel = np.ones((3, 3), np.uint8)
//iteration表示迭代的次数
imgDilation = cv2.dilate(imgCanny, kernel, iterations=1)
cv2.imshow('Dilation Image', imgDilation)
cv2.waitKey(0)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

效果
在这里插入图片描述

8.原图–>边缘图–>膨胀图–>腐蚀图

img = cv2.imread("resources/KS.jpg")
imgCanny = cv2.Canny(img, 200, 250)
kernel = np.ones((3, 3), np.uint8)
imgDilation = cv2.dilate(imgCanny, kernel, iterations=1)
imgEroded = cv2.erode(imgDilation, kernel, iterations=1)
cv2.imshow('Eroded Image', imgEroded)
cv2.waitKey(0)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

效果
在这里插入图片描述

9.图像尺寸变换

//(430, 690, 3) (h, w, 3)原始图像尺寸
img = cv2.imread("resources/car.png")
//opencv图像的起始坐标在左上角
//使用opencv变换时,输入的是(w, h) !!!
imgResize = cv2.resize(img, (350, 200))

cv2.imshow('Image', img)
cv2.imshow('Image Resize', imgResize)
cv2.waitKey(0)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

效果
在这里插入图片描述

10.图片裁剪

img = cv2.imread("resources/car.png")
// (430, 690, 3) (h, w, 3)
print(img.shape)

// 正常裁剪,输入的是(h, w) !!!
imgCropped = img[50:350, 200:500]

cv2.imshow("Image", img)
cv2.imshow("Image Cropped", imgCropped)
cv2.waitKey(0)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

效果
在这里插入图片描述

11.图片颜色变换

//创建一张全零的图片,每个像素的值范围是[0, 255]
img = np.zeros((512, 512, 3), np.uint8)
//设置每个像素的三通道值为255,0,0 (B R G)
img[:] = 255, 0, 0

cv2.imshow("Image", img)

cv2.waitKey(0)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

效果
在这里插入图片描述

12.图片上加线条

//这是一张全黑图片,像素值0代表black
img = np.zeros((512, 512, 3), np.uint8)
//设置被覆盖的图片,线的起点(w, h),终点(w, h) !!!,颜色,宽度 
cv2.line(img, (0, 0), (300, 300), (0, 255, 0), thickness=3)

cv2.imshow("Image", img)

cv2.waitKey(0)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

效果
在这里插入图片描述

13.图片上加矩形框

img = np.zeros((512, 512, 3), np.uint8)
//设置被覆盖的图片,矩形框的左上角点(w, h),右下角点(w, h) !!!,颜色,宽度 
cv2.rectangle(img, (0, 0), (250, 350), (0, 0, 255), thickness=2)

cv2.imshow("Image", img)

cv2.waitKey(0)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

效果
在这里插入图片描述

img = np.zeros((512, 512, 3), np.uint8)
//设置被覆盖的图片,矩形框的左上角点(w, h),右下角点(w, h) !!!,颜色,矩形框填充满设置的颜色
cv2.rectangle(img, (0, 0), (250, 350), (0, 0, 255), cv2.FILLED)

cv2.imshow("Image", img)

cv2.waitKey(0)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

效果
在这里插入图片描述

14.图片上加圆形

img = np.zeros((512, 512, 3), np.uint8)
//设置被覆盖的图片, 圆的中心坐标(w, h), 圆的半径,圆圈颜色,圆圈厚度
cv2.circle(img, (400, 50), 30, (255, 255, 0), 3)

cv2.imshow("Image", img)

cv2.waitKey(0)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

效果
在这里插入图片描述

15.图片上加文字

img = np.zeros((512, 512, 3), np.uint8)
//设置被覆盖的图片, 文本,文本左下角的坐标(w, h), 文本字体,字体大小,字体颜色,字体厚度
cv2.putText(img, "Hello Space!", (300, 100), fontFace=cv2.FONT_HERSHEY_COMPLEX,
            fontScale=1, color=(300, 100, 0), thickness=2)

cv2.imshow("Image", img)

cv2.waitKey(0)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

效果
在这里插入图片描述

16.透视变换

待透视变换图片
在这里插入图片描述

//待透视变换变换的图片
img = cv2.imread("./resources/card.png")
//Ace的左上角,右上角,左下角,右下角坐标(格式是ndarray)
pts1 = np.array([[146, 125], [389, 103], [192, 484], [460, 441]], dtype="float32")
//透视变换后Ace的左上角,右上角,左下角,右下角坐标(格式是ndarray)
pts2 = np.array([[0, 0], [width, 0], [0, height], [width, height]], dtype="float32")
//利用两对坐标得到透视变换矩阵matrix
matrix = cv2.getPerspectiveTransform(pts1, pts2)
//设置透视变换后Ace的w,h
width, height = 250, 350
//原图通过透视变换矩阵,变成了透视变换后的图像imgOutput
imgOutput = cv2.warpPerspective(img, matrix, (width, height))

cv2.imshow("Image", img)
cv2.imshow("Output", imgOutput)

cv2.waitKey(0)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

效果
透视变换(Perspective Transformation)是将成像投影到一个新的视平面(Viewing Plane),也称作投影映射(Projective Mapping)

17.图片堆叠显示

原始图像
在这里插入图片描述

//原始图像:一只羊
img = cv2.imread("./resources/sheep.png")
//水平方向堆叠5张
imgHor = np.hstack((img, img, img, img, img))
//垂直方向堆叠3张
imgVer = np.vstack((img, img, img))

cv2.imshow("Horizontal", imgHor)
cv2.imshow("Vertical", imgVer)
cv2.waitKey(0)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

效果
在这里插入图片描述
如果需要在堆叠前缩小或放大原始图片,可以使用方法八先把图像尺寸改变,再进行堆叠

18.图片转换成HSV形式

问:什么是HSV?
答:RGB 颜色空间是大家最熟悉的颜色空间,即三基色空间,任何一种颜色都可以由该三种 颜色混合而成。然而一般对颜色空间的图像进行有效处理都是在 HSV 空间进行的,HSV(色 调 Hue,饱和度 Saturation,亮度 Value)是根据颜色的直观特性创建的一种颜色空间。

原始图像
在这里插入图片描述

//原始图像
img = cv2.imread("./resources/KS3.jpg")
//HSV图像, 把BGR通道转变成HSV
imgHSV = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)

cv2.imshow("Original", img)
cv2.imshow("HSV", imgHSV)
cv2.waitKey(0)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

效果

19.HSV–>mask图–>HSV,mask叠加图

// 定义回调函数,此程序无需回调,所以Pass即可
def empty(a):
    pass
// 创建一个窗口叫TrackBars
cv2.namedWindow("TrackBars")
// 修改窗口的大小
cv2.resizeWindow("TrackBars", 640, 260)

HSV颜色分量范围:H:  0180   S:  0255   V:  0255
// 在这个名为TrackBars的窗口上,创建控制Hue(色调)最小值的滑动条,初始值为0, 最大到180,回调函数这个参数这里用不到,所以pass了
cv2.createTrackbar("Hue Min", "TrackBars", 0, 180, empty)
// 在这个名为TrackBars的窗口上,创建控制Hue(色调)最大值的滑动条,初始值为180, 最大到180
cv2.createTrackbar("Hue Max", "TrackBars", 180, 180, empty)
// 在这个名为TrackBars的窗口上,创建控制Sat(饱和度)最小值的滑动条,初始值为0, 最大到255
cv2.createTrackbar("Sat Min", "TrackBars", 0, 255, empty)
// 在这个名为TrackBars的窗口上,创建控制Sat(饱和度)最大值的滑动条,初始值为255, 最大到255
cv2.createTrackbar("Sat Max", "TrackBars", 255, 255, empty)
// 在这个名为TrackBars的窗口上,创建控制Val(明度)最小值的滑动条,初始值为0, 最大到255
cv2.createTrackbar("Val Min", "TrackBars", 0, 255, empty)
// 在这个名为TrackBars的窗口上,创建控制Val(明度)最大值的滑动条,初始值为255, 最大到255
cv2.createTrackbar("Val Max", "TrackBars", 255, 255, empty)
// 设定一个无限循环
while True:
	// 原图
    img = cv2.imread("./resources/car1.png")
    // HSV图
    imgHSV = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
    // 获得每个滑动条滑动到某个位置的值
    h_min = cv2.getTrackbarPos("Hue Min", "TrackBars")
    h_max = cv2.getTrackbarPos("Hue Max", "TrackBars")
    s_min = cv2.getTrackbarPos("Sat Min", "TrackBars")
    s_max = cv2.getTrackbarPos("Sat Max", "TrackBars")
    v_min = cv2.getTrackbarPos("Val Min", "TrackBars")
    v_max = cv2.getTrackbarPos("Val Max", "TrackBars")
    // 分别把最小值和最大值放入到两个ndarray中(准备参数)
    lower = np.array([h_min, s_min, v_min])
    upper = np.array([h_max, s_max, v_max])
    // 创建mask图
    第一个参数:hsv指的是输入的HSV图
	第二个参数:lower指的是图像中低于这个lower的值,图像值变为0
	第三个参数:upper指的是图像中高于这个upper的值,图像值变为0
	而在lower_red~upper_red之间的值变成255
    mask = cv2.inRange(imgHSV, lower, upper)
    
    cv2.imshow("Original", img)
    cv2.imshow("HSV", imgHSV)
    cv2.imshow("Mask", mask)
    
    cv2.waitKey(1)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49

效果
原图
在这里插入图片描述
HSV图
在这里插入图片描述
mask图
在这里插入图片描述
在这里插入图片描述

此时h_min, h_max, s_min, s_max, v_min, v_max都是默认值,显示成全白
然后对trackbar进行调节,把手动尽量把车子调节成光滑状态,如下图
在这里插入图片描述
在这里插入图片描述
然后根据现在的h_min, h_max, s_min, s_max, v_min, v_max值,修改初始值:
(下面展示完整代码)

def empty(a):
    pass

cv2.namedWindow("TrackBars")
cv2.resizeWindow("TrackBars", 640, 260)
// 修改过的h_min, h_max, s_min, s_max, v_min, v_max初始值
cv2.createTrackbar("Hue Min", "TrackBars", 0, 180, empty)
cv2.createTrackbar("Hue Max", "TrackBars", 180, 180, empty)
cv2.createTrackbar("Sat Min", "TrackBars", 6, 255, empty)
cv2.createTrackbar("Sat Max", "TrackBars", 255, 255, empty)
cv2.createTrackbar("Val Min", "TrackBars", 158, 255, empty)
cv2.createTrackbar("Val Max", "TrackBars", 255, 255, empty)

while True:
    img = cv2.imread("./resources/car1.png")
    imgHSV = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
    h_min = cv2.getTrackbarPos("Hue Min", "TrackBars")
    h_max = cv2.getTrackbarPos("Hue Max", "TrackBars")
    s_min = cv2.getTrackbarPos("Sat Min", "TrackBars")
    s_max = cv2.getTrackbarPos("Sat Max", "TrackBars")
    v_min = cv2.getTrackbarPos("Val Min", "TrackBars")
    v_max = cv2.getTrackbarPos("Val Max", "TrackBars")
    print(h_min, h_max, s_min, s_max, v_min, v_max)
    lower = np.array([h_min, s_min, v_min])
    upper = np.array([h_max, s_max, v_max])
    mask = cv2.inRange(imgHSV, lower, upper)
    // 把原图和mask图结合,原图彩色部分会填充到mask图白色部分
    imgResult = cv2.bitwise_and(img, img, mask=mask)

    cv2.imshow("Original", img)
    cv2.imshow("HSV", imgHSV)
    cv2.imshow("Mask", mask)
    cv2.imshow("Result", imgResult)
    cv2.waitKey(1)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34

效果
在这里插入图片描述
Result是不是有一种光滑油亮的感觉,也有点像卡通图

20.轮廓检测

//图片尺寸减小函数(计算机屏幕看着太大,所以减小,你可以不减小)
def image_process(img, size):
    imgResize = cv2.resize(img, (int(img.shape[1]*size), int(img.shape[0]*size)))
    return imgResize
 //显示原图
img = cv2.imread("./resources/shapes3.png")
cv2.imshow("Original", image_process(img, 0.6))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

原图
在这里插入图片描述
明确目的:在每个图形上找到并画出外轮廓,然后找到每个图的顶点,再用一个rectangle过顶角把图形框起来。

def getContours(img):
    // findContours()接收的是二值黑白图, 所以整个代码最下面调用getContours函数时传入的图片是imgCanny, imgCanny是二值黑白图(忘记的点击目录看第6个)
    // 返回两个:轮廓本身,轮廓属性
    // 参数:寻找轮廓的图像,检索外轮廓(轮廓检索模式),存储所有的轮廓点(轮廓的近似办法)
    contours, hierarchy = cv2.findContours(img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
    for cnt in contours:
        // 计算轮廓面积
        area = cv2.contourArea(cnt)
        // 画出轮廓面积大于2000的轮廓(筛选一下)
        if area > 2000:
            // 参数:待画轮廓图像,待画轮廓,轮廓索引(-1表示都画),轮廓颜色, 轮廓线条粗细
            cv2.drawContours(imgContour, cnt, -1, (255, 0, 0), 3)
            // 计算轮廓的周长
            peri = cv2.arcLength(cnt, closed=True)
            // 判断点到相对应的line segment 的距离的阈值。
            // 距离大于此阈值则舍弃,小于此阈值则保留,epsilon越小,折线的形状越“接近”曲线。
            approx = cv2.approxPolyDP(cnt, 0.02*peri, closed=True)
            // 每个图形,角的个数
            objCor = len(approx)
            // 获得每个图形角外套的框的左上角坐标,以及w,h
            x, y, w, h = cv2.boundingRect(approx)
			// 如果顶角数为3,判定为三角形
            if objCor == 3:
                objectType = "Tri"
            // 如果顶角数为4
            elif objCor == 4:
                aspRatio = w/h
                // 如果0.95 < 宽高比 < 1.05,就是正方形(因为实际图片长宽不一定完全相等)
                if aspRatio > 0.95 and aspRatio < 1.05:
                    objectType = "Square"
                // 不在这个范围,基本判定为长方形
                else:
                    objectType = "Rectangle"
            // 如果大于4, 就是圆形
            elif objCor > 4:
                objectType = "Circle"
            // 如果有其它情况,标注为None
            else:
                objectType="None"
            // 画框,参数:待画框的图,框左上角,右下角的坐标,框的颜色,框的粗细
            cv2.rectangle(imgContour, (x, y), (x+w, y+h), (0, 255, 0), 2)
            // 添加文字,参数:待画框的图,文本信息,文本左下角的坐标(w, h),字体,字体大小,字体颜色,字体粗细
            cv2.putText(imgContour, objectType, int((x+(w/2)-10), int(y+(h/2)-10)), cv2.FONT_HERSHEY_COMPLEX, 0.8, (0, 0, 0), 2)


img = cv2.imread("./resources/shapes3.png")
// 拷贝一份彩图,轮廓,检测框,文字都要添加再这张图上
imgContour = img.copy()
getContours(imgCanny)

def image_process(img, size):
    imgResize = cv2.resize(img, (int(img.shape[1]*size), int(img.shape[0]*size)))
    return imgResize
    
// 原图尺寸缩小为原来的0.6倍
cv2.imshow("Original", image_process(img, 0.6))
cv2.waitKey(0)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57

效果
在这里插入图片描述
可能因为截图的原因,倒数第二排红色三角行轮廓没有检测出来, 因为筛选了area(轮廓面积), 所以绿色小三角形没有框起来和标注

21.人脸检测

// 安装opencv时自动带的文件夹里有这些xml文件,找不到的直接百度搜索haarcascades下载
// 我测试了很多不同类型的图片,haarcascades的精度相对低一些,但是速度还可以,在一些手机摄像头和特定情况下上还是有使用的
// 读取文件
faceCascade = cv2.CascadeClassifier("./haarcascades/haarcascade_frontalface_default.xml")
// 读取要检测的图片
img = cv2.imread("./resources/KS16.png")
// trick:使用灰度图可以提升检测速度
imgGray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
// 确定脸,参数:1.1(每次缩小图像的比例,默认是1.1), 4(匹配成功所需要的周围矩形框的数目,每一个特征匹配到的区域都是一个矩形框,只有多个矩形框同时存在的时候,才认为是匹配成功,比如人脸,这个默认值是3。)
faces = faceCascade.detectMultiScale(imgGray, 1.1, 4)
// 遍历所有脸的x, y, w, h,拿到rectangle的左上角有右下角坐标,画框
// (x, y)左上角坐标,(x+w, y+h)右下角坐标,(147, 20, 255)框的颜色,2 框的粗细
for (x, y, w, h) in faces:
    cv2.rectangle(img, (x, y), (x+w, y+h), (147, 20, 255), 2)

cv2.imshow("Result", img)
cv2.waitKey(0)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

效果
在这里插入图片描述
在这里插入图片描述

22.综合应用1–屏幕水彩笔

我们先来看下效果:
效果
在这里插入图片描述
(对应颜色的笔可以在屏幕上画画)

你需要准备:几只全彩笔,每支笔的壳色需是同一种颜色
在这里插入图片描述
(我准备的笔不标准,大家准备标准的,效果更好)

// 目标:是要得到两只笔的黑白mask图
// 这一步可以参考 19.如何得到汽车图片的mask图,原理一样,只是我这里用的是摄像头,获取的是动态的一帧帧的图片
import cv2
import numpy as np
// 创建摄像头,创建显示窗口大小
frameWidth = 320
frameHeight = 240
cap = cv2.VideoCapture(0)
cap.set(3, frameWidth)
cap.set(4, frameHeight)
cap.set(10, 150)

def empty(a):
    pass
// 创建名为TrackBars的窗口
cv2.namedWindow("TrackBars")
// 修改窗口大小,设置初始值,回调函数为空
cv2.resizeWindow("TrackBars", 640, 260)
cv2.createTrackbar("Hue Min", "TrackBars", 0, 180, empty)
cv2.createTrackbar("Hue Max", "TrackBars", 180, 180, empty)
cv2.createTrackbar("Sat Min", "TrackBars", 0, 255, empty)
cv2.createTrackbar("Sat Max", "TrackBars", 255, 255, empty)
cv2.createTrackbar("Val Min", "TrackBars", 0, 255, empty)
cv2.createTrackbar("Val Max", "TrackBars", 255, 255, empty)
// 设置无限循环
while True:
	// 获得摄像头看到的图像
    success, img = cap.read()
    // 把原图转换成HSV图
    imgHSV = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
    // 分别获得滑动块运动后所在位置的值
    h_min = cv2.getTrackbarPos("Hue Min", "TrackBars")
    h_max = cv2.getTrackbarPos("Hue Max", "TrackBars")
    s_min = cv2.getTrackbarPos("Sat Min", "TrackBars")
    s_max = cv2.getTrackbarPos("Sat Max", "TrackBars")
    v_min = cv2.getTrackbarPos("Val Min", "TrackBars")
    v_max = cv2.getTrackbarPos("Val Max", "TrackBars")
	// 存入mask的两个阈值
    lower = np.array([h_min, s_min, v_min])
    upper = np.array([h_max, s_max, v_max])
    // 因为滑动块的6个值都是初始值,所以此时mask是全白图
    // 然后你就手动调节,分别把两只笔调节成光滑白色,然后分别记录下此时的HSV 6个值。效果图见下:
    mask = cv2.inRange(imgHSV, lower, upper)
    
    cv2.imshow("Original", img)
    cv2.imshow("Mask", mask)
    if cv2.waitKey(1) & 0xFF == ord('s'):
        break
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48

效果
在这里插入图片描述
在这里插入图片描述
(所以你一共要记录两组值,每组6个)

此时再单独再建一个工程文件,里面放的是主要的函数及代码
下面我来单独讲一下这些函数的功能, 让我们开始吧!

// 此函数目的是获取笔尖的坐标
def getContours(img):
    // findContours()接收的是二值黑白图, 所以整个代码最下面调用getContours函数时传入的图片是imgCanny, imgCanny是二值黑白图(忘记的点击目录看第6个)
    // 返回两个:轮廓本身,轮廓属性
    // 参数:寻找轮廓的图像,检索外轮廓(轮廓检索模式),存储所有的轮廓点(轮廓的近似办法)
    contours, hierarchy = cv2.findContours(img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
    // 设置boundingrect的x,y,w,h初始值为0
    x, y, w, h = 0, 0, 0, 0
    for cnt in contours:
        # 计算轮廓面积
        area = cv2.contourArea(cnt)
        // 画出轮廓面积大于500的轮廓(筛选一下)
        if area > 500:
            // 注意:画cnt这步我们不需要,我们要轮廓的目的是为了得到这个轮廓的boundingRect,然后获得rect的x, y, w, h。当然你也可以画出来。
            // cv2.drawContours(imgResult, cnt, -1, (255, 0, 0), 3)
            // 计算轮廓的周长
            peri = cv2.arcLength(cnt, closed=True)
            // 判断点到相对应的line segment 的距离的阈值。
            // 距离大于此阈值则舍弃,小于此阈值则保留,epsilon越小,折线的形状越“接近”曲线。
            approx = cv2.approxPolyDP(cnt, 0.02*peri, closed=True)
            // 获得每个图形角外套的框的左上角坐标,以及w,h
            x, y, w, h = cv2.boundingRect(approx)
    return x+w//2, y
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
// 因为我们最后会有一个无限循环,所以每次笔移动一帧,在笔尖处都会得到一个新的point,这步的目的就是获得这个新的点的坐标以及这个点的颜色,颜色当然要和笔颜色一致
// 这是我在调节mask的6个值后记录下的两组值,你用你自己的
myColors = [[93, 31, 35, 172, 136, 255],   # 粉色笔
            [107, 31, 30, 123, 206, 239]]  # 蓝色笔
// 在网上搜索找到笔对应颜色的BGR值
myColorValues = [[228, 204, 255],  # BGR 粉色
                 [255, 153, 51]]   #     蓝色

def findColor(img, myColors, myColorValues):
    imgHSV = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
    count = 0
    newPoints = []
    for color in myColors:
        lower = np.array(color[0:3])
        upper = np.array(color[3:6])
        mask = cv2.inRange(imgHSV, lower, upper)
        // 利用上一步的函数,得到笔尖坐标
        x, y = getContours(mask)
        cv2.circle(imgResult, (x,y), 10, myColorValues[count], cv2.FILLED)
        // 因为我们上一步设置了area>500, 所以小于500的就没有boundingrect,也就x, y, w, h就变成了初始值0了, 返回的点没有用。那当然这里我们不考虑小于500的情况(这根据你实际需求自定义)
        if x!= 0 and y!=0:
        // 大列表里放入一个小列表,内容是x,y,即笔尖坐标,count这里取0或者1,后面画笔尖点时可以取myColorValues里面的BGR颜色
            newPoints.append([x, y, count])
        count += 1
     // 返回新笔尖点信息(坐标,颜色下标)
    return newPoints
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
// 用来存储新的点
myPoints = []
  • 1
  • 2
// 定义一个画出笔尖点的函数
def drawOnCanvas(myPoints, myColorValues):
    // 遍历列表,得到里面的列表
    for point in myPoints:
        // 再取里面列表里的元素,即坐标,颜色下标
        cv2.circle(imgResult, (point[0], point[1]), 10, myColorValues[point[2]], cv2.FILLED)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
// 建立无限循环
while True:
    success, img = cap.read()
    imgResult = img.copy()
    newPoints = findColor(img, myColors, myColorValues)
    if len(newPoints) != 0:
        for newP in newPoints:
            myPoints.append(newP)
    if len(myPoints) !=0:
        drawOnCanvas(myPoints, myColorValues)
        
    cv2.imshow("Result", imgResult)
    if cv2.waitKey(1) & 0xFF == ord('s'):
        break
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

23.综合应用2–车牌检测

这里我用了一个电脑外接摄像头,启用后去照另一台电脑上的汽车图片,来检测车牌,下面我们开始讲解代码吧!

// parameters
// 设置摄像区域宽,高参数
frameWidth = 640
frameHeight = 480
// 建立检测车牌的对象(没有haarcascade_russian_plate_number.xml的百度搜索下载)
nplateCascade = cv2.CascadeClassifier("./haarcascades/haarcascade_russian_plate_number.xml")
// 设置最小车牌检测区域
minArea = 500
// 因为车牌检测到后我们还要标注文字,这是设置文字的颜色
color = (255, 0, 255)
// 这是一个国外的RGB颜色网站,喜欢的颜色值从上面参考选取即可
// 网址:[添加链接描述](https://www.gif.cn/)

// 设置摄像头宽,高,明亮度
cap = cv2.VideoCapture(1)
cap.set(3, frameWidth)
cap.set(4, frameHeight)
cap.set(10, 150)
// 设置一个count数,后面保存不同车牌时需要不同的图片文件名
count = 0

while True:
    success, img = cap.read()
    // 每次读取到的图片转成灰度图(可以提升检测速度)
    imgGray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    // 使用车牌检测对象来检测车牌信息
    // 参数含义参考 21 人脸检测
    numberPlates = nplateCascade.detectMultiScale(imgGray, 1.1, 4)
    // 因为可能检测到多张车牌,所以遍历里面的信息
    for (x, y, w, h) in numberPlates:
        area = w * h
        // 车牌面积大于500的检测(这个根据实际情况去定)
        if area > minArea:
            // 图片上加检测框
            // 参数:图片,左上角,右下角,颜色,框的粗细
            cv2.rectangle(img, (x, y), (x+w, y+h), (147, 20, 255), 2)
            // 图片上加文本
            // 参数:图片,文本,文本左下角坐标,字体,字体大小,颜色,字体粗细
            cv2.putText(img, "Number Plate", (x, y-5),
                        cv2.FONT_HERSHEY_COMPLEX_SMALL, 1, color, 2)
            // 找到Roi感受区域,即图片中车牌那块区域
            imgRoi = img[y:y+h, x:x+w]
            // 单独显示Roi感受区域
            cv2.imshow("ROI", imgRoi)


    cv2.imshow("Result", img)
    // 如果按s键,会触发以下内容
    if cv2.waitKey(1) & 0xFF == ord("s"):
        // 把感受区域中的图片,即车牌保存到一下本地路劲
        cv2.imwrite("resources/Scanned/NoPlate_"+str(count)+".jpg", imgRoi)
        // 同时图片上加一块全绿色区域
        cv2.rectangle(img, (0, 200), (640, 300), (0, 255, 0), cv2.FILLED)
        // 全绿色区域上再加以下字样(表示车牌图保存成功)
        cv2.putText(img, "Scan Saved!", (150, 265), cv2.FONT_HERSHEY_DUPLEX,
                    2, (0, 0, 255), 2)
        // 因为是加在img原图上的,所以此时要再显示一次原图
        cv2.imshow("Result", img)
        // 停顿半秒,让保存按照顺序进行
        cv2.waitKey(500)
        // 累加1,图片命名就不重复了
        count += 1
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62

效果
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/100468
推荐阅读
相关标签
  

闽ICP备14008679号