python opencv图像笔记

下载依赖

选择镜像源,这样下载快一点

切换源

清华:https://pypi.tuna.tsinghua.edu.cn/simple
阿里云:http://mirrors.aliyun.com/pypi/simple/
中国科技大学 https://pypi.mirrors.ustc.edu.cn/simple/

python opencv图像笔记
python opencv图像笔记
python opencv图像笔记
python opencv图像笔记

安装依赖

python opencv图像笔记
python opencv图像笔记

; 第一个打开图片的代码

import cv2

def start():
    img = cv2.imread('C:\\Users\\Zz\\Pictures\\VRChat\\2022-06\\vr.png')
    cv2.imshow('展示',img)
     #等待一段时间
    cv2.waitKey(0)

if __name__ == '__main__':
   start()

效果图

python opencv图像笔记

创建和显示窗口

namedWindow(winname,flag)  命名窗口名称和窗口类型
imshow() 显示窗口
destoryAllWindows() 销毁所有窗口
resizeWindow() 设置窗口大小

namedWindow(winname,flag)中flag的参数

  • WINDOW_NORMAL 可以拖动大小
  • WINDOW_AUTOSIZE 操作窗口的用户不能改变窗口的大小,窗口的大小取决于图像的大小。
  • WINDOW_OPENGL 创建的窗口可支持OPENGL。OpenGL(英语:Open Graphics Library,译名:开放图形库或者”开放式图形库”)是用于渲染2D、3D矢量图形的跨语言、跨平台的应用程序编程接口(API)。
  • WINDOW_FULLSCREEN 创建的窗口以全屏的形式显示…但实际操作中发现并没有实现全屏显示
  • WINDOW_FREERATIO 图像窗口可以以任意宽高比例显示,即不固定宽高比例
  • WINDOW_KEEPRATIO 图像窗口的宽高比例保持不变。
  • WINDOW_GUI_EXPANDED 图像窗口可以添加状态栏和工具栏。
  • WINDOW_GUI_NORMAL 老式窗口,即没有状态栏和工具栏的图像窗口

演示

import cv2

def start():
    cv2.namedWindow("窗口",cv2.WINDOW_NORMAL)
     cv2.resizeWindow("窗口",1920,1080)
    cv2.imshow("窗口",0)

    key=cv2.waitKey(0)
    if(key & 0xFF==ord('q')):
        cv2.destroyAllWindows()

if __name__ == '__main__':
   start()

加载显示图片

imread(path,flag)

imread(path,flag)中flag的参数

cv2.IMREAD_COLOR:默认参数,读入一副彩色图片,忽略alpha通道,可用1作为实参替代
cv2.IMREAD_GRAYSCALE:读入灰度图片,可用0作为实参替代
cv2.IMREAD_UNCHANGED:顾名思义,读入完整图片,包括alpha通道,可用-1作为实参替代
PS:alpha通道,又称A通道,是一个8位的灰度通道,该通道用256级灰度来记录图像中的透明度复信息,定义透明、不透明和半透明区域,其中黑表示全透明,白表示不透明,灰表示半透明

演示:

import cv2

def start():
    cv2.namedWindow("窗口",cv2.WINDOW_NORMAL)
    img = cv2.imread('C:\\Users\\Zz\\Pictures\\VRChat\\2022-06\\vr.png',cv2.IMREAD_GRAYSCALE)
    cv2.imshow("窗口",img)

    key=cv2.waitKey(0)
    if(key & 0xFF==ord('q')):
        cv2.destroyAllWindows()

if __name__ == '__main__':
   start()

保存图片

imwrite(name,img)
name,要保存的文件名
img,是Mat类型
import cv2

def start():
    cv2.namedWindow("窗口",cv2.WINDOW_NORMAL)
    img = cv2.imread('C:\\Users\\Zz\\Pictures\\VRChat\\2022-06\\vr.png',cv2.IMREAD_GRAYSCALE)
    cv2.imshow("窗口",img)

    key=cv2.waitKey(0)
    print(key)
    if(key & 0xFF==ord('q')):
        cv2.destroyAllWindows()
    elif(key & 0xFF==ord('s')):
        cv2.imwrite("C:\\Users\\Zz\\Desktop\\img.png",img)
    cv2.destroyAllWindows()

if __name__ == '__main__':
   start()

调用摄像头

VideoCapure()  视频采集器 一般设备号从0开始   第二个参数为api,不同平台api不一样
cap.read()  读取视频帧  返回两个值,一个为状态值,读到帧为true,另一个为视频帧
cap.release()  释放资源
import cv2

def start():
    # 创建窗口
    cv2.namedWindow("窗口",cv2.WINDOW_NORMAL)

    #获取视频设备
    cap=cv2.VideoCapture("http://admin:123456@192.168.0.100:8081")

    while True:
        ret,frame=cap.read()
        cv2.imshow("窗口",frame)
        key=cv2.waitKey(1)
        if (key & 0xFF == ord('q')):
            break
    cap.release()
    cv2.destroyAllWindows()

if __name__ == '__main__':
   start()

从多媒体文件中读取视频帧

import cv2

def start():
    # 创建窗口
    cv2.namedWindow("窗口",cv2.WINDOW_NORMAL)
    #获取多媒体视频
    cap=cv2.VideoCapture("C:\\Users\\Zz\\Desktop\\2.mp4")

    while True:
        ret,frame=cap.read()
        cv2.imshow("窗口",frame)
        key=cv2.waitKey(10)
        if (key & 0xFF == ord('q')):
            break
    cap.release()
    cv2.destroyAllWindows()

if __name__ == '__main__':
   start()

将视频数据录制成多媒体

VideoWriter  参数一为输出文件  参数二为多媒体文件格式(VideoWrite_fourcc) 参数三为帧率  参数四为分辨率大小 参数四为是否带有颜色默认true
write
release
cv.VideoWriter_fourcc('M','J','P','G') 或者cv.VideoWriter_fourcc(*'MJPG')

代码演示

import cv2

def start():
    #fourcc= cv2.VideoWriter_fourcc('M','J','P','G')
    #因为这里保存的是视频,所以用MP4v
    fourcc = cv2.VideoWriter_fourcc('m', 'p', '4', 'v')

    vw=cv2.VideoWriter("C:\\Users\\Zz\\Desktop\\3.mp4",fourcc,25,(1920,1080))
    # 创建窗口
    cv2.namedWindow("窗口",cv2.WINDOW_NORMAL)

    #获取多媒体视频
    cap=cv2.VideoCapture("C:\\Users\\Zz\\Desktop\\2.mp4")

    while True:
        ret,frame=cap.read()
        cv2.imshow("窗口",frame)
        #写数据到多媒体
        vw.write(frame)
        key=cv2.waitKey(1)
        if (key & 0xFF == ord('q')):
            break
    cap.release()
    cv2.destroyAllWindows()
    #释放资源
    vw.release()

if __name__ == '__main__':
   start()

代码优化

1.视频窗口被撑大
因为视频分辨率比较大,把窗口撑大,我们可以在循环中设置窗口大小

    while True:
        ret,frame=cap.read()
        cv2.imshow("窗口",frame)
        cv2.resizeWindow("窗口",1920,1080)
        #写数据到多媒体
        vw.write(frame)
        key=cv2.waitKey(1)
        if (key & 0xFF == ord('q')):
            break

2.检测摄像头是否被打开
isOpened()

while cap.isOpened():
    ret,frame=cap.read()
    if ret == True:
        cv2.imshow("窗口",frame)
        cv2.resizeWindow("窗口",1920,1080)
        #写数据到多媒体
        vw.write(frame)
        key=cv2.waitKey(1)
        if (key & 0xFF == ord('q')):
            break
      else:
            break

openCV控制鼠标

setMouseCallback(winname,callback,userdata)  第一个参数是窗口名 第二个参数是回调函数 第三个函数是给回调函数传参
callback(event,x,y,flags,userdata)   event:鼠标移动、按下左键    x,y:鼠标坐标    flags:鼠标键及组合键

实操代码

import cv2
import numpy as np

def mouse_callback(event,x,y,flags,userdata):
    print(event,x,y,flags,userdata)

def start():
    cv2.namedWindow("mouse",cv2.WINDOW_NORMAL)
    cv2.resizeWindow('mouse',640,360)
    #设置鼠标回调
    cv2.setMouseCallback('mouse',mouse_callback,"123")
    #生成纯黑照片
    img=np.zeros((360,640,3),np.uint8)
    while True:
        cv2.imshow("mouse",img)
        key = cv2.waitKey(1)
        if key & 0xFF ==ord('q'):
            break

if __name__ == '__main__':
   start()

python opencv图像笔记

TrackBar 控件

createTrackbar(trackbarname,winname,value:trackbar,count,callback,userdata) 第一个参数控件的名字,第二个是窗口的名字,第三个是当前值
第四个是最大值 最小值为0。第五个是回调函数和传参
getTrackbarPos(trackbarname,winname)输出当前值

import cv2
import numpy as np

def callback():
    pass

def start():
    cv2.namedWindow('tracker',cv2.WINDOW_NORMAL)
    cv2.createTrackbar('R','tracker',0,255,callback)
    cv2.createTrackbar('G', 'tracker', 0, 255, callback)
    cv2.createTrackbar('B', 'tracker', 0, 255, callback)

    img=np.zeros((480,460,3),np.uint8)

    while True:
        r=cv2.getTrackbarPos('R',"tracker")
        g=cv2.getTrackbarPos('G', "tracker")
        b=cv2.getTrackbarPos('B', "tracker")
        #操作所有像素
        img[:] = [b,g,r]
        cv2.imshow("tracker", img)

        key=cv2.waitKey(10)
        if (key &0xFF ==ord('q')):
            break
    cv2.destroyAllWindows()

if __name__ == '__main__':
   start()

python opencv图像笔记

opencv中的色彩空间

  • 色彩空间变换
  • 像素访问
  • 矩阵的加减乘除
  • 基本图形的绘制

颜色空间

  • RGB:人眼的色彩空间 (主要用在显示器物理硬件中)
  • opencv默认使用BGR
  • HSV/HSB/HSL 第一个HSV是色相色调饱和度 第二个是明亮度 第三个???
  • YUV 主要用于视频 ,视频储存节省空间

HSV (主要用在opencv)

  • Hue:色相,即色彩,如红色、蓝色
  • Saturation : 饱和度,颜色的纯度
  • Value:明度

HSL

  • Hue:色相,即色彩,如红色、蓝色
  • Saturation : 饱和度,颜色的纯度
  • Ligthness:明度

YUV

三种类型 对像素的描述 黑白 色彩

  • YUV4:2:0
  • YUV4:2:2
  • YUV4:4:4

色彩空间转换

import cv2
import numpy as np

def callback():
    pass

def start():
    cv2.namedWindow('color',cv2.WINDOW_NORMAL)

    img = cv2.imread('C:\\Users\\Zz\\Pictures\\VRChat\\2022-06\\vr.png')
    cv2.imshow("color",img)

    colorspace = [cv2.COLOR_BGR2RGBA,cv2.COLOR_BGR2BGRA,cv2.COLOR_BGR2GRAY,cv2.COLOR_BGR2HSV,cv2.COLOR_BGR2YUV]
    cv2.createTrackbar('curcolor','color',0,len(colorspace)-1,callback)

    while True:
        index=cv2.getTrackbarPos('curcolor','color')
        #颜色转换API
        cvt_img=cv2.cvtColor(img,colorspace[index])
        cv2.imshow('color',cvt_img)

        key=cv2.waitKey(10)
        if (key &0xFF ==ord('q')):
            break
    cv2.destroyAllWindows()

if __name__ == '__main__':
   start()

Numpy

Opencv中用到的矩阵都要转换为Numpy数组
Numpy是一个高度优化的python数值库

Numpy基本操作

  1. 创建矩阵
  2. 检索与赋值[y,x]
  3. 获取子矩阵[:,:]
创建矩阵 array()
创建全0矩阵 zeros() / ones
创建全值数组 full()
创建单元数组 identity/eye()

1.array

  • a=np.array([2,3,4])
  • c=np.array([[2,3,4],[6,5,4]])

2.zeros

  • a=np.zeros((480,640,3),np.uint8)
    (480,640,3) (行的个数,列的个数,通道数/层数)
    np.uint8是矩阵中的数据类型

3.ones

  • a=np.ones((480,640,3),np.uint8)
    (480,640,3) (行的个数,列的个数,通道数/层数)
    np.uint8是矩阵中的数据类型

4.full

  • a=np.full((480,640,3),255,np.uint8)
    (480,640,3) (行的个数,列的个数,通道数/层数)
    np.uint8是矩阵中的数据类型
    255是每个元素的数值

5.identity 单元矩阵

  • c=np.identity(3)
    斜对角是1,其它为0
[1,0,0]
[0,1,0]
[0,0,1]

5.eye

  • c=np.eye(3,4,k=2)
    斜对角是1,其它为0
    k=2 代表从第二个开始
[0,0,1,0]
[0,0,0,1]
[0,0,0,0]

Numpy 检索与赋值

  • [y,x] //灰度
  • [y,x,channel] //RGB
import cv2
import numpy as np

def callback():
    pass

def start():
    cv2.namedWindow('color',cv2.WINDOW_NORMAL)

    img = np.zeros((720,720,3),np.uint8)
    x = 0
    while x<360: #绿色通道,所以会成为绿色 img[360,x,1]="255" x="x+1" cv2.imshow("color",img) key="cv2.waitKey(0)" if (key &0xff="=ord('q')):" cv2.destroyallwindows() __name__="=" '__main__': start() < code></360:>

python opencv图像笔记

这样赋值也可以

img[360, x] = [0,0,255]

Region of Image(ROI)

Numpy获取子矩阵

  • [y1:y2:x1:x2]
  • [:,:] 所有图像操作
    roi=img[100:200:,100:200]
    roi[:,:]=[0,255,0]

    img[100:200:,100:200]= [0,255,0]
    cv2.imshow("color",img)

python opencv图像笔记

opencv最重要的结构体Mat

Mat是什么? Mat是一个矩阵
Mat有什么好处? 可以通过umpy矩阵的方式来访问

Mat:

python opencv图像笔记
mat头部属性:
class CV_EXPORTS Mat{
    public:
    ...
    int dims; //&#x7EF4;&#x6570;
    int rows,cols; //&#x884C;&#x5217;&#x6570;
    uchar *data //&#x50A8;&#x5B58;&#x6570;&#x636E;&#x7684;&#x6307;&#x9488;
    int *refcount; //&#x5F15;&#x7528;&#x8BA1;&#x6570; &#x907F;&#x514D;&#x5185;&#x5B58;&#x6CC4;&#x6F0F;
    ...

}

字段说明dims维度rows行数cols列数depth像素位深channels通道数RGB是3size矩阵大小typedep+dt+chs CV_8UC3data存放数据

Mat 拷贝

浅拷贝

python opencv图像笔记
import cv2
import numpy as np
def callback():
    pass
def start():
    cv2.namedWindow('color',cv2.WINDOW_NORMAL)
    img = cv2.imread('C:\\Users\\Zz\\Pictures\\VRChat\\2022-06\\vr.png')
    #&#x6D45;&#x62F7;&#x8D1D;
    img2=img
    index = 0

    img2[10:500,10:500]=[0,255,255]

    cv2.imshow("color",img)
    while True:
        key=cv2.waitKey(10)
        if (key &0xFF ==ord('q')):
            break
    cv2.destroyAllWindows()

if __name__ == '__main__':
   start()

python opencv图像笔记
深拷贝
 # &#x6DF1;&#x62F7;&#x8D1D;
    img2=img.copy()

访问Mat的属性

  • img.shape ————- 打印结果: (4032,3024,3) #高度,长度和通道数
  • img.size ————- 打印结果: 36578304 #高度x长度x通道数=
  • img.dtype ————- 打印结果:uint8 位深

通道分离与合并

  • split(mat) 分离通道
  • merge((ch1,ch2,…))融合通道
import cv2
import numpy as np

def callback():
    pass

def start():
    cv2.namedWindow('color',cv2.WINDOW_NORMAL)

    img = np.zeros((480,640,3),np.uint8)

    b,g,r=cv2.split(img)

    b[10:100,10:100]=255
    g[210:300,210:300]=110
    r[50:250,50:250]=255

    img2 = cv2.merge((b,g,r))
    cv2.imshow("color", img2)
    cv2.waitKey(0)

    cv2.destroyAllWindows()

if __name__ == '__main__':
   start()

python opencv图像笔记

opencv绘制图形

划线

line(img,&#x5F00;&#x59CB;&#x70B9;,&#x7ED3;&#x675F;&#x70B9;,&#x989C;&#x8272;...)

参数详解

  1. img:在哪个图像上画线
  2. 开始点结束点:指定线的开始位置和结束位置
  3. 颜色、线宽、线形
  4. Shift:坐标缩放比例
import cv2
import numpy as np

def start():
    img=np.zeros((480,640,3),np.uint8)

    #&#x753B;&#x7EBF;(x,y) 5&#x662F;&#x7EBF;&#x5BBD; 16&#x662F;&#x7EBF;&#x578B;&#xFF08;&#x6297;&#x952F;&#x9F7F;&#xFF09;
    cv2.line(img,(100,20),(400,400),(0,0,255),5,16)
    cv2.line(img, (200, 20), (400, 600), (0, 0, 255), 5, 4)
    cv2.imshow("&#x753B;&#x677F;", img)

    cv2.waitKey(0)

if __name__ == '__main__':
    start()

python opencv图像笔记
绘制椭圆
ellipse(img,&#x4E2D;&#x5FC3;&#x70B9;&#xFF0C;&#x957F;&#x5BBD;&#x7684;&#x4E00;&#x534A;&#xFF0C;&#x89D2;&#x5EA6;&#xFF0C;&#x4ECE;&#x54EA;&#x4E2A;&#x89D2;&#x5EA6;&#x5F00;&#x59CB;&#xFF0C;&#x4ECE;&#x54EA;&#x4E2A;&#x89D2;&#x5EA6;&#x7ED3;&#x675F;...)

是按顺时针计算,0度从右侧开始

 #&#x753B;&#x692D;&#x5706;
    cv2.ellipse(img,(240,320),(100,50),0,0,360,(0,0,255))

python opencv图像笔记
#&#x753B;&#x692D;&#x5706;
    cv2.ellipse(img,(240,320),(100,50),0,45,360,(0,0,255),-1)

python opencv图像笔记

opencv 绘制多边形

polylines(img,&#x70B9;&#x96C6;,&#x662F;&#x5426;&#x95ED;&#x73AF;,&#x989C;&#x8272;,...)    #&#x70B9;&#x96C6;&#x5FC5;&#x987B;&#x662F;32&#x4F4D;

代码:

 #&#x753B;&#x591A;&#x8FB9;&#x5F62;
    pts= np.array([(300,10),(150,100),(450,100)],np.int32)
    cv2.polylines(img,[pts],True,(0,0,255))

运行效果:

python opencv图像笔记
填充多边形
fillPoly(img,&#x70B9;&#x96C6;,&#x989C;&#x8272;)

代码:

 #&#x586B;&#x5145;&#x591A;&#x8FB9;&#x5F62;
    cv2.fillPoly(img,[pts],(255,0,0))

运行效果:

python opencv图像笔记

opencv绘制文本

cv2.putText(img,&#x5B57;&#x7B26;&#x4E32;,&#x542F;&#x59CB;&#x70B9;,&#x5B57;&#x4F53;,&#x5B57;&#x53F7;,...)

代码:

#&#x7ED8;&#x5236;&#x6587;&#x672C;
    cv2.putText(img,"&#x6211;&#x8D85;hello!!",(250,150),cv2.FONT_HERSHEY_PLAIN,1,(0,0,255))

运行效果:

python opencv图像笔记

课后作业画板

import cv2
import numpy as np

start=(0,0)
end=(0,0)
num=0

def mouse_callback(event,x,y,flags,userdata):
    global start
    global end
    #print(event, x, y, flags, userdata)
    if(event& cv2.EVENT_LBUTTONDOWN==cv2.EVENT_LBUTTONDOWN):
        start=(x,y)
        print(start)
    elif(event& cv2.EVENT_LBUTTONUP==cv2.EVENT_LBUTTONUP):
        end=(x,y)
        print(end)
        le= (abs( start[0]-end[0]),abs(start[1]-end[1]))

        print(le)
        if(userdata[0]=='c'):
            cv2.ellipse(userdata[2],start,le,0,0,360,userdata[1])
        else:
            cv2.line(userdata[2],start,end,userdata[1],5)
    cv2.imshow("drawtable",userdata[2])

def start():
    #&#x521B;&#x5EFA;&#x4E00;&#x4E2A;&#x9ED1;&#x8272;&#x56FE;&#x7247;
    img = np.zeros((480,640,3),np.uint8)
    #&#x663E;&#x793A;&#x9ED1;&#x8272;&#x56FE;&#x7247;
    cv2.imshow("drawtable",img)

    # &#x901A;&#x8FC7;&#x8BFB;&#x53D6;&#x6309;&#x952E;&#x6765;&#x6267;&#x884C;
    shape = 'l'
    color = (0, 0, 225)
    #&#x76D1;&#x542C;&#x9F20;&#x6807;
    cv2.setMouseCallback("drawtable",mouse_callback,[shape, color,img])
    while True:
        # &#x7B49;&#x5F85;&#x83B7;&#x53D6;&#x6309;&#x952E;
        key = cv2.waitKey(0)
        if(panduankey(key,'q')):
            break
        elif(panduankey(key,'c')):
            shape='c'
        elif(panduankey(key,'l')):
            shape='l'
        elif(panduankey(key,'r')):
            color=(0,0,225)
        elif (panduankey(key, 'b')):
            color =(225,0,225)
        cv2.setMouseCallback("drawtable", mouse_callback, [shape, color,img])

    cv2.destroyAllWindows()

def panduankey(key,let):
    if (key &0xFF== ord(let)):
        return True
    else:
        return False

if __name__ == '__main__':
    start()

python opencv图像笔记

图运算

  • 两个图相加
  • 两个图相减
  • 两个图相乘
  • 两个图相除

1.两张图相加

import cv2
import numpy as np

def start():
    cv2.namedWindow('color', cv2.WINDOW_NORMAL)
    img = cv2.imread('C:\\Users\\Zz\\Pictures\\VRChat\\2022-06\\vr.png')
    img2= np.ones(img.shape,np.uint8) *50

    img3= cv2.add(img,img2)
    cv2.imshow('color',img3)

    cv2.waitKey(0)

if __name__ == '__main__':
    start()

效果:图片更白了

python opencv图像笔记

2.两张图相减

subtract(A,B) #A&#x51CF;B

3.两张图相乘

multiply(A,B) #&#x4EAE;&#x7684;&#x66F4;&#x591A;&#x4E00;&#x4E9B;

4.两张图相除

divide(A,B) #&#x6697;&#x7684;&#x66F4;&#x591A;&#x4E00;&#x4E9B;

图像融合

addWeighted(A,alpha,B,bate,gamma)
  • alpha和beta是 a和b权重
  • gamma 静态权重

代码:

import cv2
import numpy as np

def start():
    cv2.namedWindow('color', cv2.WINDOW_NORMAL)
    img = cv2.imread('C:\\Users\\Zz\\Pictures\\VRChat\\2022-06\\vr.png')
    img2= cv2.imread('C:\\Users\\Zz\\Pictures\\VRChat\\2022-06\\vr2.png')
    img3= cv2.addWeighted(img,0.7,img2,0.3,0)
    cv2.imshow('color',img3)

    cv2.waitKey(0)

if __name__ == '__main__':
    start()

效果图

python opencv图像笔记

图像位运算

  • 异或

1.非运算

bitwise_not(img)

代码:

import cv2
import numpy as np

def start():
    cv2.namedWindow('color', cv2.WINDOW_NORMAL)
    img = np.zeros((200,200),np.uint8)
    img[50:150,50:150] =255
    img2= cv2.bitwise_not(img)
    cv2.imshow('img', img)
    cv2.imshow('img2',img2)

    cv2.waitKey(0)

if __name__ == '__main__':
    start()

显示:

python opencv图像笔记
2.与运算
    cv2.bitwise_and(img,img2)

代码:

import cv2
import numpy as np

def start():
    cv2.namedWindow('color', cv2.WINDOW_NORMAL)
    img = np.zeros((200,200),np.uint8)
    img2 = np.zeros((200, 200), np.uint8)

    img[20:120,20:120] =255
    img2[80:180,80:180] =255

    img3= cv2.bitwise_and(img,img2)
    cv2.imshow('img', img)
    cv2.imshow('img2',img2)
    cv2.imshow('img3', img3)

    cv2.waitKey(0)

if __name__ == '__main__':
    start()

效果:

python opencv图像笔记
3.或运算
    cv2.bitwise_or(img,img2)

效果:

python opencv图像笔记

4.异或运算

    cv2.bitwise_xor(img,img2)

效果:

python opencv图像笔记

给图片添加水印

  1. 引入一张图片
  2. 创建一个logo
  3. 计算在什么位置添加,在添加的地方变黑
  4. 利用add 将logo与图片叠加到一起
    代码:
import cv2
import numpy as np

def start():
    img = cv2.imread('C:\\Users\\Zz\\Pictures\\VRChat\\2022-06\\vr.png')

    logo = np.zeros((200,200,3),np.uint8)
    mask= np.zeros((200,200),np.uint8)

    #&#x7ED8;&#x5236;logo
    logo[20:120,20:120] =[0,0,255]
    logo[80:180, 80:180] = [0, 255, 0]

    mask[20:120,20:120] =255
    mask[80:180, 80:180] = 255

    #&#x5BF9;mask&#x6C42;&#x53CD;
    m=cv2.bitwise_not(mask)

    #&#x9009;&#x62E9;img&#x6DFB;&#x52A0;logo&#x7684;&#x4F4D;&#x7F6E;
    roi =img[0:200,0:200]

    #&#x4E0E;m&#x8FDB;&#x884C;&#x4E0E;&#x64CD;&#x4F5C;
    tmp=cv2.bitwise_and(roi,roi,mask=m)
    dst=cv2.add(tmp,logo)

    img[0:200,0:200] = dst

    cv2.imshow('img', img)

    cv2.waitKey(0)

if __name__ == '__main__':
    start()

演示:

python opencv图像笔记

图片加汉字生成二维码

首先引入 qrcode和pillow库
然后下载字体文件下载地址
代码:

import cv2
import numpy as np
from PIL import Image,ImageDraw,ImageFont
import qrcode

'''&#x628A;&#x4E8C;&#x7EF4;&#x7801;&#x653E;&#x7F6E;&#x5728;&#x539F;&#x56FE;&#x7684;&#x53F3;&#x4E0B;&#x89D2;'''
def comblex_pic(base_img, myQR):
    myQR_w, myQR_h = myQR.size
    base_img_w, base_img_h = base_img.size
    paste_location = (base_img_w-myQR_w, base_img_h-myQR_h, base_img_w, base_img_h)
    base_img.paste(myQR, paste_location)
    return base_img

def start():
    img = cv2.imread('C:\\Users\\Zz\\Pictures\\VRChat\\2022-06\\vr.png')

    logo = np.zeros((200,200,3),np.uint8)
    mask= np.zeros((200,200),np.uint8)

    #&#x7ED8;&#x5236;logo
    logo[20:120,20:120] =[0,0,255]
    logo[80:180, 80:180] = [0, 255, 0]

    mask[20:120,20:120] =255
    mask[80:180, 80:180] = 255

    #&#x5BF9;mask&#x6C42;&#x53CD;
    m=cv2.bitwise_not(mask)

    #&#x9009;&#x62E9;img&#x6DFB;&#x52A0;logo&#x7684;&#x4F4D;&#x7F6E;
    roi =img[0:200,0:200]

    #&#x4E0E;m&#x8FDB;&#x884C;&#x4E0E;&#x64CD;&#x4F5C;
    tmp=cv2.bitwise_and(roi,roi,mask=m)
    dst=cv2.add(tmp,logo)

    img[0:200,0:200] = dst

    #&#x5C06;img&#x8F6C;&#x6362;&#x4E3A;PIL&#x683C;&#x5F0F;
    img_pil=Image.fromarray(cv2.cvtColor(img,cv2.COLOR_BGR2RGB))
    #&#x5B57;&#x4F53;&#x8DEF;&#x5F84;
    font=ImageFont.truetype('font.ttf',38)
    #&#x5B57;&#x4F53;&#x989C;&#x8272;
    fillColor=(0,0,225)
    draw=ImageDraw.Draw(img_pil)
    draw.text((1000,500),"&#x8FD9;&#x662F;&#x4E00;&#x6761;&#x4FE1;&#x606F;",font=font,fill=fillColor)

    #&#x4E8C;&#x7EF4;&#x7801;
    imgqrc = qrcode.make("https://www.bilibili.com/")
    # &#x4E8C;&#x7EF4;&#x7801;&#x6DFB;&#x52A0;&#x81F3;&#x539F;&#x56FE;&#x53F3;&#x4E0B;&#x89D2;
    comblepic = comblex_pic(img_pil, imgqrc)
    # &#x663E;&#x793A;&#x56FE;&#x7247;
    comblepic.show()

    print(img)

    # &#x8F6C;&#x56DE;opencv&#x683C;&#x5F0F;
    img = cv2.cvtColor(np.asarray(img_pil), cv2.COLOR_RGB2BGR)

    cv2.imshow('img', img)

    cv2.waitKey(0)

if __name__ == '__main__':
    start()

效果:

python opencv图像笔记

图像的变换

1.图像的缩放

resize(src,dst,dsize,fx,fy,interpolation)   //&#x7B2C;&#x4E00;&#x4E2A;&#x53C2;&#x6570;&#x56FE;&#x7247;&#x5730;&#x5740; &#x7B2C;&#x4E8C;&#x4E2A;&#x53C2;&#x6570;&#x8F93;&#x51FA;&#x53C2;&#x6570;&#xFF08;python&#x4E2D;&#x4E0D;&#x7528;&#xFF09; &#x7B2C;&#x4E09;&#x4E2A;&#x53C2;&#x6570;&#x7F29;&#x653E;&#x5927;&#x5C0F; fx&#xFF1A;x&#x8F74;&#x7F29;&#x653E;&#x56E0;&#x5B50; fy&#xFF1A;y&#x8F74;&#x7684;&#x7F29;&#x653E;&#x56E0;&#x5B50; interpolation &#x7F29;&#x653E;&#x7B97;&#x6CD5;

interpolation 缩放算法:

  1. INTER_NEAREST 临近插值,速度快,效果差
  2. INTER_LINEAR 双线性插值,原图中的四个点(默认)
  3. INTER_CUBIC 三次插值,原图中的16个点
  4. INTER_AREA,效果最好
import cv2
import numpy as np

def start():
    img = cv2.imread('C:\\Users\\Zz\\Pictures\\VRChat\\2022-06\\vr.png')

    img2= cv2.resize(img,(400,400))   // img2 = cv2.resize(img, None,fx=0.3,fy=0.3,interpolation=cv2.INTER_AREA)
    #&#x4E0E;m&#x8FDB;&#x884C;&#x4E0E;&#x64CD;&#x4F5C;

    cv2.imshow('img', img2)

    cv2.waitKey(0)

if __name__ == '__main__':
    start()

2.图像反转

flip(img,flipCode)
  • fileCode==0,上下
  • fileCode>0,左右
  • fileCode
import cv2
import numpy as np

def start():
    img = cv2.imread('C:\\Users\\Zz\\Pictures\\VRChat\\2022-06\\vr.png')

    img2=cv2.flip(img,0)

    cv2.imshow('img', img2)

    cv2.waitKey(0)

if __name__ == '__main__':
    start()

3.图像的旋转

rotate(img,rotateCode)
  • ROTATE_90_CLOCKWIZE
  • ROTATE_180
  • ROTATE_90_COUNTERCLOCKWISE (旋转270度)
import cv2
import numpy as np

def start():
    img = cv2.imread('C:\\Users\\Zz\\Pictures\\VRChat\\2022-06\\vr.png')

    img2=cv2.rotate(img,cv2.ROTATE_90_COUNTERCLOCKWISE)

    cv2.imshow('img', img2)

    cv2.waitKey(0)

if __name__ == '__main__':
    start()

3.图像的仿射变换
仿射变换是图像的旋转、缩放、平移的总称

warpAffine(src,M,dsize,flags,mode,value)
M:&#x53D8;&#x6362;&#x77E9;&#x9635;
dsize:&#x8F93;&#x51FA;&#x5C3A;&#x5BF8;&#x5927;&#x5C0F;
flags&#xFF1A;&#x4E0E;resize&#x4E2D;&#x7684;&#x63D2;&#x503C;&#x7B97;&#x6CD5;&#x4E00;&#x81F4;
mode:&#x8FB9;&#x754C;&#x5916;&#x63A8;&#x6CD5;&#x6807;&#x5FD7;
value&#xFF1A;&#x586B;&#x5145;&#x8FB9;&#x754C;&#x7684;&#x503C;

平移矩阵
矩阵中每个像素由(x,y)组成
因此,其变换矩阵是2×2的矩阵
平移向量位2×1的向量,所以平移矩阵位2×3矩阵
代码:

import cv2
import numpy as np

def start():
    img = cv2.imread('C:\\Users\\Zz\\Pictures\\VRChat\\2022-06\\vr.png')

    #&#x5FC5;&#x987B;&#x662F;32&#x4F4D;&#xFF0C;&#x56E0;&#x4E3A;&#x8BA1;&#x7B97;&#x7CBE;&#x5EA6;&#x8F83;&#x9AD8;
    M=np.float32([[1,0,100],[0,1,0]])
    h,w,ch=img.shape
    img2=cv2.warpAffine(img,M,(w,h))

    cv2.imshow('img', img2)

    cv2.waitKey(0)

if __name__ == '__main__':
    start()

图片:

python opencv图像笔记
变换矩阵
getRotationMatrix2D(center,angle,scale)
center &#x4E2D;&#x5FC3;&#x70B9;
angle &#x89D2;&#x5EA6;
scale &#x7F29;&#x653E;&#x6BD4;&#x4F8B;
import cv2
import numpy as np

def start():
    img = cv2.imread('C:\\Users\\Zz\\Pictures\\VRChat\\2022-06\\vr.png')

    #&#x5FC5;&#x987B;&#x662F;32&#x4F4D;&#xFF0C;&#x56E0;&#x4E3A;&#x8BA1;&#x7B97;&#x7CBE;&#x5EA6;&#x8F83;&#x9AD8;
    #M=np.float32([[1,0,100],[0,1,0]])
    h,w,ch=img.shape
    M2= cv2.getRotationMatrix2D((100,100),15,1.5)
    img2=cv2.warpAffine(img,M2,(w,h))

    cv2.imshow('img', img2)

    cv2.waitKey(0)

if __name__ == '__main__':
    start()

效果:

python opencv图像笔记
中心点旋转
  #(w/2,h/2)&#x4E2D;&#x5FC3;&#x70B9;
  M2= cv2.getRotationMatrix2D((w/2,h/2),15,1.5)

修改图片修改后的大小

#&#x5982;&#x679C;&#x60F3;&#x8981;&#x4FEE;&#x6539;&#x56FE;&#x7247;&#x5927;&#x5C0F;&#xFF0C;&#x9700;&#x8981;&#x5728;&#x8FD9;&#x91CC;&#x4FEE;&#x6539;
    img2 = cv2.warpAffine(img, M2, (w/2, h/2))

变换矩阵 二

getAffineTransform(src[],dst[])
&#x4E09;&#x4E2A;&#x70B9;&#x53EF;&#x4EE5;&#x786E;&#x5B9A;&#x53D8;&#x6362;&#x7684;&#x4F4D;&#x7F6E;
import cv2
import numpy as np

def start():
    img = cv2.imread('C:\\Users\\Zz\\Pictures\\VRChat\\2022-06\\vr.png')

    #&#x5FC5;&#x987B;&#x662F;32&#x4F4D;&#xFF0C;&#x56E0;&#x4E3A;&#x8BA1;&#x7B97;&#x7CBE;&#x5EA6;&#x8F83;&#x9AD8;
    src=np.float32([[400,300],[800,300],[400,1000]])
    dst=np.float32([[200,400],[600,500],[150,1100]])
    h,w,ch=img.shape
    #(w/2,h/2)&#x4E2D;&#x5FC3;&#x70B9;
    M2= cv2.getAffineTransform(src,dst)
    print(M2)
    #&#x5982;&#x679C;&#x60F3;&#x8981;&#x4FEE;&#x6539;&#x56FE;&#x7247;&#x5927;&#x5C0F;&#xFF0C;&#x9700;&#x8981;&#x5728;&#x8FD9;&#x91CC;&#x4FEE;&#x6539;
    img2 = cv2.warpAffine(img, M2, (w, h))

    cv2.imshow('img', img2)

    cv2.waitKey(0)

if __name__ == '__main__':
    start()

效果:

python opencv图像笔记

滤波器

滤波的作用
一幅图像通过滤波器得到另一幅图像;
其中滤波器又称为卷积核,滤波的过程成为卷积;

python opencv图像笔记
锐化
卷积的过程
python opencv图像笔记
卷积的几个基本概念
  • 卷积核的大小
  • 锚点
  • 边界扩充
  • 步长

卷积核的大小
卷积核一般是奇数,如3×3,5×5、7×7
原因是:

  1. 增加padding的原因
  2. 保证锚点在中间,防止位置发生偏移的原因

卷积核大小的影响
在深度学习中,卷积核越大,得到的信息(感受野)越大,提取的特征越好,同时计算量也越大

锚点

python opencv图像笔记

边界扩充

  • 当卷积核大于1且不进行边界扩充,输出尺寸将相应缩小
  • 当卷积核以标准方式进行边界扩充,则输出数据的空间尺寸将与输入相等

计算公式

N = (W - F + 2P)/S+1
N&#x8F93;&#x51FA;&#x56FE;&#x50CF;&#x5927;&#x5C0F;
W&#x6E90;&#x56FE;&#x5927;&#x5C0F;&#xFF1B;F&#x5377;&#x79EF;&#x6838;&#x5927;&#x5C0F;&#xFF1B;P&#x6269;&#x5145;&#x5C3A;&#x5BF8;
S&#x6B65;&#x957F;&#x5927;&#x5C0F;

步长

python opencv图像笔记

实战图像卷积

低通滤波与高通滤波

  • 低通滤波可以去除噪音和平滑图像
  • 高通滤波可以帮助查找图像边缘

图像卷积

filter2D(src,ddepth,kernel,anchor,delta,borderType)
ddepth &#x4F4D;&#x6DF1; &#x4E00;&#x822C;-1
kernel &#x5377;&#x79EF;&#x6838;
anchor &#x951A;&#x70B9;
delta &#x9ED8;&#x8BA4;&#x662F;0
borderType &#x8FB9;&#x754C;&#x7C7B;&#x578B;

代码:

import cv2
import numpy as np

def start():
    img = cv2.imread('C:\\Users\\Zz\\Pictures\\VRChat\\2022-06\\vr.png')

    kernal=np.ones((5,5),np.float32)/25
    img2=cv2.filter2D(img,-1,kernal)

    cv2.imshow('img', img2)

    cv2.waitKey(0)

if __name__ == '__main__':
    start()

效果:

python opencv图像笔记

方盒滤波与均值滤波

python opencv图像笔记
参数a的作用
&#x65B9;&#x76D2;&#x6EE4;&#x6CE2;&#x53C2;&#x6570; normalize
normalize = true &#xFF0C; a= 1/(W x H)
normalize = false &#xFF0C; a= 1

当 normalize = true时 方盒滤波==平均滤波
两个滤波的API

boxFilter(src,ddepth,ksize,anchor,normalize,borderType)
ddepth &#x8F93;&#x51FA;&#x4F4D;&#x6DF1; &#x4E00;&#x822C;&#x4FDD;&#x6301;&#x4E00;&#x81F4;
ksize &#x5377;&#x79EF;&#x6838;&#x5927;&#x5C0F;
anchor &#x951A;&#x70B9;  &#x53D6;&#x9ED8;&#x8BA4;&#x503C;
normalize
bordeType

方盒滤波

blur(src,ksize,anchor,borderType)

平均滤波

import cv2
import numpy as np

def start():
    img = cv2.imread('C:\\Users\\Zz\\Pictures\\VRChat\\2022-06\\vr.png')
    #&#x5377;&#x79EF;&#x6838;
    #kernal=np.ones((5,5),np.float32)/25
    img2=cv2.blur(img,(5,5))

    cv2.imshow('img', img2)

    cv2.waitKey(0)

if __name__ == '__main__':
    start()

效果图

python opencv图像笔记

高斯滤波

python opencv图像笔记
python opencv图像笔记
python opencv图像笔记
高斯滤波API
GaussianBlur(img,kernel,sigmaX,sigmaY,...)
kernel &#x6838;&#x5927;&#x5C0F;
sigmaX &#x91CD;&#x5FC3;&#x6EE4;&#x6CE2;&#x5EF6;&#x5C55;&#x7684;&#x5BBD;&#x5EA6; x&#x8F74;  &#x5230;&#x4E2D;&#x5FC3;&#x70B9;&#x7684;&#x6700;&#x5927;&#x5DEE;&#x8DDD; &#x8D8A;&#x5927;&#x8D8A;&#x6A21;&#x7CCA;

代码:

import cv2
import numpy as np

def start():
    img = cv2.imread('C:\\Users\\Zz\\Pictures\\VRChat\\2022-06\\vr.png')
    #&#x5377;&#x79EF;&#x6838;
    #kernal=np.ones((5,5),np.float32)/25
    img2=cv2.GaussianBlur(img,(5,5),sigmaX=1)

    cv2.imshow('img', img2)

    cv2.waitKey(0)

if __name__ == '__main__':
    start()

效果图:

python opencv图像笔记
高斯滤波主要解决高斯噪点。
python opencv图像笔记

中值滤波

假设有一个数组【1556789】,取其中的中间值作为卷积的结果值
中值滤波的优点是对胡椒噪音效果明显

python opencv图像笔记
medianBlur(img,ksize)

代码:

import cv2
import numpy as np

def start():
    img = cv2.imread('C:\\Users\\Zz\\Pictures\\2.png')

    #5x5
    img2=cv2.medianBlur(img,5)

    cv2.imshow('img', img2)

    cv2.waitKey(0)

if __name__ == '__main__':
    start()

效果

python opencv图像笔记

双边滤波

可以保留边缘,同时可以对边缘内的区域进行平滑处理。
双边滤波作用就是进行美颜

python opencv图像笔记
双边滤波API
bilateralFilter(img,d,sigmaColor,sigmaSpace,...)
d &#x76F4;&#x5F84; dilter&#x5927;&#x5C0F;
sigmaColor &#x8FB9;&#x7F18;
sigmaSpace &#x5E73;&#x9762;&#x4E0A;

代码:

import cv2
import numpy as np

def start():
    img = cv2.imread('C:\\Users\\Zz\\Pictures\\VRChat\\2022-06\\vr.png')

    img2=cv2.bilateralFilter(img,7,20,50)

    cv2.imshow('img', img2)

    cv2.waitKey(0)

if __name__ == '__main__':
    start()

高通滤波

  • Sobel(索贝尔)(高斯)——抗噪音好—–缺点:必须将横轴和纵轴检测的边缘加在一起才能
  • Scharr(沙尔)——3×3卷积核,检测的更细一点—–缺点:必须将横轴和纵轴检测的边缘加在一起才能
  • Laplacian(lapulasi)——-可以将横轴纵轴一起检测—–缺点:对噪音敏感

Sobel算子

  1. 先向x方向求导
  2. 然后在y方向求导
  3. 最终结果:|G| = |Gx| + |Gy|

Sobel API:

Sobel(src,ddepth,dx,dy,ksize=3,scale=1&#xFF0C;delta=0&#xFF0C;borderType=BORDER_DEFAULT)
dx=1 &#x5C31;&#x4F1A;&#x68C0;&#x6D4B;y&#x8FB9;
dy=1 &#x5C31;&#x4F1A;&#x68C0;&#x6D4B;x&#x8FB9;
&#x5982;&#x679C;ksize=-1&#x5C31;&#x53D8;&#x6210;Scharr&#x7B97;&#x6CD5;
scale &#x7F29;&#x653E;
delta &#x7ED3;&#x679C;
borderType &#x8FB9;&#x7F18;&#x7C7B;&#x578B;&#x662F;&#x4EC0;&#x4E48;

代码:

import cv2
import numpy as np

def start():
    img = cv2.imread('C:\\Users\\Zz\\Pictures\\VRChat\\2022-06\\vr.png')

    #y&#x65B9;&#x5411;&#x8FB9;&#x7F18;
    d1=cv2.Sobel(img,cv2.CV_64F,1,0,ksize=5)
    d2 = cv2.Sobel(img, cv2.CV_64F, 0, 1, ksize=5)
    dst=d1+d2

    cv2.imshow('d1', d1)
    cv2.imshow('d2', d2)
    cv2.imshow('dst', dst)
    cv2.waitKey(0)

if __name__ == '__main__':
    start()

效果:

python opencv图像笔记

Scharr算子

  • 与Sobel类似,只不过使用的Kernel值不同
  • Scharr只能求x方向或y方向边缘

ScharrAPI:

Scharr(src,ddepth,dx,dy,scale=1,delta=0,borderType=BORDER_DEFAULT)

代码:

import cv2
import numpy as np

def start():
    img = cv2.imread('C:\\Users\\Zz\\Pictures\\VRChat\\2022-06\\vr.png')

    d1=cv2.Scharr(img,cv2.CV_64F,1,0)
    d2 = cv2.Scharr(img, cv2.CV_64F, 0, 1)
    dst=d1+d2

    cv2.imshow('d1', d1)
    cv2.imshow('d2', d2)
    cv2.imshow('dst', dst)
    cv2.waitKey(0)

if __name__ == '__main__':
    start()

效果图:

python opencv图像笔记

拉普拉斯算子Laplacian

  • 可以同时求两个方向的边缘
  • 对噪音敏感,一般先进行去噪再调用拉普拉斯

Laplacian API

Laplacian(img,ddepth,ksize=1,scale=1,borderType=BORDER_DEFAULT)

代码:

import cv2
import numpy as np

def start():
    img = cv2.imread('C:\\Users\\Zz\\Pictures\\VRChat\\2022-06\\vr.png')

    d1=cv2.Laplacian(img,cv2.CV_64F,ksize=5)

    cv2.imshow('d1', d1)

    cv2.waitKey(0)

if __name__ == '__main__':
    start()

效果图:

python opencv图像笔记

边缘检测Canny

  • 使用5×5高斯滤波消除噪音
  • 计算图像梯度的方向(0°、45°、90°、135°)
  • 取局部最大值
    python opencv图像笔记
    Canny API :
Canny(img,minVal,maxVal,...)
minVal&#x6700;&#x5C0F;&#x9608;&#x503C; &#x5C0F;&#x4E8E;&#x6700;&#x5C0F;&#x9608;&#x503C;&#x5C31;&#x4E0D;&#x7B97;&#x8FB9;&#x7F18;
maxVal&#x6700;&#x5927;&#x9608;&#x503C; &#x5927;&#x4E8E;&#x6700;&#x5927;&#x9608;&#x503C;&#x662F;&#x8FB9;&#x7F18;

代码:

import cv2
import numpy as np

def start():
    img = cv2.imread('C:\\Users\\Zz\\Pictures\\VRChat\\2022-06\\vr.png')

    d1=cv2.Canny(img,100,200)

    cv2.imshow('d1', d1)

    cv2.waitKey(0)

if __name__ == '__main__':
    start()

效果图:

python opencv图像笔记

形态学图像处理

  • 基于图像形态进行处理的一些基本算法
  • 这些处理方法基本是对二进制图像进行处理
  • 卷积核决定着图像处理后的效果

处理方法:

  1. 腐蚀与膨胀
  2. 开运算
  3. 闭运算
  4. 顶帽
  5. 黑帽

图像二值化

  • 将图像的每个像素变成两种值,如0,255
  • 全局二值化
  • 局部二值化 (对光线不好的图像处理较好)
    全局二值化
    threshold API
threshold(img,thresh,maxVal,type)
img:&#x56FE;&#x50CF;&#xFF0C;&#x6700;&#x597D;&#x662F;&#x7070;&#x5EA6;&#x56FE;
thresh&#xFF1A;&#x9608;&#x503C;
maxVal&#xFF1A;&#x8D85;&#x8FC7;&#x9608;&#x503C;&#xFF0C;&#x66FF;&#x6362;&#x6210;maxVal

threshodType

  • THRESH_BINARY和THRESH_BINARY_INV (两个相反,一个超过阈值为最大,一个超过阈值为最小 )
  • THRESH_TRUNC
  • THRESH_TOZERO和THRESH_TOZERO_INV

python opencv图像笔记

代码:

import cv2

def start():
    img = cv2.imread('C:\\Users\\Zz\\Pictures\\VRChat\\2022-06\\vr.png')
    gol= cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

    #&#x4E00;&#x4E2A;&#x662F;&#x6267;&#x884C;&#x7ED3;&#x679C;&#xFF0C;&#x4E00;&#x4E2A;&#x662F;&#x8F93;&#x51FA;&#x56FE;&#x50CF;
    ret,dst=cv2.threshold(gol,180,255,cv2.THRESH_BINARY)

    cv2.imshow('dst', dst)

    cv2.waitKey(0)

if __name__ == '__main__':
    start()

效果图:

python opencv图像笔记

自适应阈值

由于光照不均匀以及阴影的存在,只有一个阈值会使得在阴影处的白色被二值化成黑色

adaptiveThreshold API

adaptiveThreshold(img,maxVal,adaptiveMethod ,type,blockSize,C)
maxVal &#x8F6C;&#x6362;&#x6210;&#x6700;&#x5927;&#x503C;&#x662F;&#x591A;&#x5C11;
adaptiveMethod:&#x8BA1;&#x7B97;&#x9608;&#x503C;&#x7684;&#x65B9;&#x6CD5;
blockSize &#x4E34;&#x8FD1;&#x533A;&#x57DF;&#x5927;&#x5C0F;
C &#x5E38;&#x91CF;&#xFF0C;&#x4ECE;&#x8BA1;&#x7B97;&#x51FA;&#x7684;&#x5E73;&#x5747;&#x503C;&#x6216;&#x52A0;&#x6743;&#x5E73;&#x5747;&#x503C;&#x4E2D;&#x51CF;&#x53BB;

adaptiveMethod:

  • 计算阈值的方法
  • ADAPTIVE_THRESH_MEAN_C:计算临近区域的平均值
  • ADAPTIVE_THRESH_GAUSSIAN_C :高斯窗口加权平均值 (一般用这个效果更好)

Type:二值化类型

  • THRESH_BINARY
  • THRESH_BINARY_INV
    代码:
import cv2

def start():
    img = cv2.imread('C:\\Users\\Zz\\Pictures\\VRChat\\2022-06\\vr.png')
    gol= cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

    #&#x4E00;&#x4E2A;&#x662F;&#x6267;&#x884C;&#x7ED3;&#x679C;&#xFF0C;&#x4E00;&#x4E2A;&#x662F;&#x8F93;&#x51FA;&#x56FE;&#x50CF;
    dst=cv2.adaptiveThreshold(gol,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY_INV,3,0)

    cv2.imshow('dst', dst)

    cv2.waitKey(0)

if __name__ == '__main__':
    start()

效果:

python opencv图像笔记

python opencv图像笔记

python opencv图像笔记
卷积核一般是全1的
python opencv图像笔记
python opencv图像笔记
腐蚀api
erode(img,kernel,iterations=1)
kernel&#x5377;&#x79EF;&#x6838;&#x5927;&#x5C0F;
iterations &#x8150;&#x8680;&#x6B21;&#x6570;

代码:

import cv2
import numpy as np

def start():
    img = cv2.imread('C:\\Users\\Zz\\Pictures\\VRChat\\2022-06\\vr.png')
    gol= cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

    kernel=np.ones((3,3),np.uint8)
    #&#x4E00;&#x4E2A;&#x662F;&#x6267;&#x884C;&#x7ED3;&#x679C;&#xFF0C;&#x4E00;&#x4E2A;&#x662F;&#x8F93;&#x51FA;&#x56FE;&#x50CF;
    dst=cv2.erode(img,kernel,iterations=1)

    cv2.imshow('dst', dst)

    cv2.waitKey(0)

if __name__ == '__main__':
    start()

效果图:

python opencv图像笔记

卷积核的类型

&#x83B7;&#x5F97;&#x5377;&#x79EF;&#x6838;
getStructuringElement(type,size)
size&#x503C;&#x4E3A;&#xFF08;3&#xFF0C;3&#xFF09;&#x3001;&#xFF08;5&#xFF0C;5&#xFF09;...

卷积核类型

  • MORPH_RECT //全一的矩形 (通常)
  • MORPH_ELLIPSE //椭圆形
  • MORPH_CROSS // 十字架 交叉的

代码:

import numpy as np

def start():
    img = cv2.imread('C:\\Users\\Zz\\Pictures\\VRChat\\2022-06\\vr.png')
    gol= cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

    #kernel=np.ones((3,3),np.uint8)
    kernel=cv2.getStructuringElement(cv2.MORPH_RECT,(7,7))

    print(kernel)

    dst=cv2.erode(img,kernel,iterations=1)

    cv2.imshow('dst', dst)

    cv2.waitKey(0)

if __name__ == '__main__':
    start()

效果:

python opencv图像笔记
MORPH_RECT //全一的矩形 (通常):
F:\python\Scripts\python.exe F:/pythonProject/opencvStudy/study1/start35.py
[[1 1 1 1 1 1 1]
 [1 1 1 1 1 1 1]
 [1 1 1 1 1 1 1]
 [1 1 1 1 1 1 1]
 [1 1 1 1 1 1 1]
 [1 1 1 1 1 1 1]
 [1 1 1 1 1 1 1]]
  • MORPH_ELLIPSE //椭圆形 :
F:\python\Scripts\python.exe F:/pythonProject/opencvStudy/study1/start35.py
[[0 0 0 1 0 0 0]
 [0 1 1 1 1 1 0]
 [1 1 1 1 1 1 1]
 [1 1 1 1 1 1 1]
 [1 1 1 1 1 1 1]
 [0 1 1 1 1 1 0]
 [0 0 0 1 0 0 0]]

MORPH_CROSS // 十字架 交叉的:

[[0 0 0 1 0 0 0]
 [0 0 0 1 0 0 0]
 [0 0 0 1 0 0 0]
 [1 1 1 1 1 1 1]
 [0 0 0 1 0 0 0]
 [0 0 0 1 0 0 0]
 [0 0 0 1 0 0 0]]

python opencv图像笔记

膨胀API:

dilate(img,kernel,iterations=1)
iterations:&#x81A8;&#x80C0;&#x51E0;&#x6B21;

代码:

import cv2
import numpy as np

def start():
    img = cv2.imread('C:\\Users\\Zz\\Pictures\\VRChat\\2022-06\\vr.png')
    gol= cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

    #kernel=np.ones((3,3),np.uint8)
    kernel=cv2.getStructuringElement(cv2.MORPH_CROSS,(7,7))

    print(kernel)

    dst=cv2.dilate(img,kernel,iterations=1)

    cv2.imshow('dst', dst)

    cv2.waitKey(0)

if __name__ == '__main__':
    start()

效果:

python opencv图像笔记

开运算

开运算=腐蚀+膨胀
开运算API:

morphologyEx(img,MORPH_OPEN,kernel)
MORPH_OPEN &#x5B8F; &#x4EE3;&#x8868;&#x5F62;&#x6001;&#x5B66;&#x7684;&#x5F00;&#x8FD0;&#x7B97;
kernel &#x5377;&#x79EF;&#x6838;&#x5927;&#x5C0F;&#x3002;&#x566A;&#x70B9;&#x5927;&#x6838;&#x5927;

代码:

import cv2
import numpy as np

def start():
    img = cv2.imread('C:\\Users\\Zz\\Pictures\\VRChat\\2022-06\\vr.png')

    kernel = cv2.getStructuringElement(cv2.MORPH_RECT,(7,7))
    dst=cv2.morphologyEx(img,cv2.MORPH_OPEN,kernel)

    cv2.imshow('dst', dst)

    cv2.waitKey(0)

if __name__ == '__main__':
    start()

效果:

python opencv图像笔记

闭运算

闭运算=膨胀+腐蚀

python opencv图像笔记
闭运算API:
morphologyEX(img,MORPH_CLOSE,kernel)

代码:

import cv2
import numpy as np

def start():
    img = cv2.imread('C:\\Users\\Zz\\Pictures\\VRChat\\2022-06\\vr.png')

    kernel = cv2.getStructuringElement(cv2.MORPH_RECT,(7,7))
    dst=cv2.morphologyEx(img,cv2.MORPH_CLOSE,kernel)

    cv2.imshow('dst', dst)

    cv2.waitKey(0)

if __name__ == '__main__':
    start()

效果:

python opencv图像笔记

形态学梯度

梯度=原图-腐蚀

python opencv图像笔记
梯度API:
morphologyEX(img,MORPH_GRADIENT,kernel)
&#x8FB9;&#x7F18;&#x6E05;&#x6670; kernel&#x5C0F;&#x4E00;&#x70B9;&#xFF0C;&#x5E0C;&#x671B;&#x91CC;&#x8FB9;&#x6BD4;&#x8F83;&#x7C97;&#x4E00;&#x70B9; kernel&#x5927;&#x4E00;&#x70B9;

代码:

import cv2
import numpy as np

def start():
    img = cv2.imread('C:\\Users\\Zz\\Pictures\\VRChat\\2022-06\\vr.png')

    kernel = cv2.getStructuringElement(cv2.MORPH_RECT,(3,3))
    dst=cv2.morphologyEx(img,cv2.MORPH_GRADIENT,kernel)

    cv2.imshow('dst', dst)

    cv2.waitKey(0)

if __name__ == '__main__':
    start()

效果图:

python opencv图像笔记

顶帽运算

顶帽=原图-开运算

python opencv图像笔记

顶帽API

morphologyEX(img,MORPH_TOPHAT,kernel)

代码:

import cv2
import numpy as np

def start():
    img = cv2.imread('C:\\Users\\Zz\\Pictures\\VRChat\\2022-06\\vr.png')

    kernel = cv2.getStructuringElement(cv2.MORPH_RECT,(3,3))
    dst=cv2.morphologyEx(img,cv2.MORPH_TOPHAT,kernel)

    cv2.imshow('dst', dst)

    cv2.waitKey(0)

if __name__ == '__main__':
    start()

效果图:

python opencv图像笔记

黑帽运算

黑帽=原图-闭运算

python opencv图像笔记

黑帽API:

morphologyEX(img,MORPH_BLACKHAT,kernel)

代码:

import cv2
import numpy as np

def start():
    img = cv2.imread('C:\\Users\\Zz\\Pictures\\VRChat\\2022-06\\vr.png')

    kernel = cv2.getStructuringElement(cv2.MORPH_RECT,(3,3))
    dst=cv2.morphologyEx(img,cv2.MORPH_BLACKHAT,kernel)

    cv2.imshow('dst', dst)

    cv2.waitKey(0)

if __name__ == '__main__':
    start()

效果图:

python opencv图像笔记

图像轮廓

具有相同颜色或强度的连续点的曲线
轮廓作用:

  1. 可用于图形分析
  2. 物体的识别和检测
    注意点:
  3. 为了检测到准确性,需要先对图像进行二值化或Canny操作
  4. 画轮廓时会修改输入的图像

轮廓查找API

findContours(img,mode,ApproximationMode...)
mode &#x6A21;&#x5F0F; &#x4E3B;&#x8981;&#x4F5C;&#x7528;&#x5BF9;&#x67E5;&#x627E;&#x5230;&#x8F6E;&#x5ED3;&#x600E;&#x6837;&#x5904;&#x7F6E;
ApproximationMode &#x8FD1;&#x4F3C;&#x7684;&#x6A21;&#x5F0F;

&#x4E24;&#x4E2A;&#x8FD4;&#x56DE;&#x503C;
contours &#x548C;hierarchy
contours &#x67E5;&#x627E;&#x5230;&#x6240;&#x6709;&#x8F6E;&#x5ED3;&#x7684;&#x5217;&#x8868;
hierarchy &#x6240;&#x6709;&#x8F6E;&#x5ED3;&#x6709;&#x6CA1;&#x6709;&#x5C42;&#x7EA7;&#x5173;&#x7CFB;&#xFF0C;&#x524D;&#x540E;&#x5173;&#x7CFB;

mode

  • RETR_EXTERNAL=0,表示只检测外轮廓
  • RETR_LIST——1,检测的轮廓不建立等级关系
  • RETR_CCOMP=2,每层最多两级
  • RETR_TREE=3,按树形存储轮廓 (常用)

python opencv图像笔记
python opencv图像笔记
python opencv图像笔记
ApproximationMode
  • CHAIN_APPROX_NONE,保存所有轮廓上的点 (数据量大)
  • CHAIN_APPROX_SIMPLE,只保存角点(一般这个)

实战查找轮廓

代码:

import cv2
import numpy as np

def start():
    img = cv2.imread('C:\\Users\\Zz\\Pictures\\VRChat\\2022-06\\vr.png')
    #&#x8F6C;&#x6362;&#x6210;&#x7070;&#x5EA6;
    imggray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
    #&#x4E8C;&#x503C;&#x5316;
    dst = cv2.adaptiveThreshold(imggray,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY_INV,3,0)
    #&#x8F6E;&#x5ED3;&#x67E5;&#x627E;
    contours,hierarchy = cv2.findContours(dst,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
    print(contours)
    print(hierarchy)

    cv2.waitKey(0)

if __name__ == '__main__':
    start()

效果:

python opencv图像笔记

绘制轮廓

绘制轮廓API:

drawContours(img, contours,contourIdx,color,thickness...)
contours&#xFF1A;&#x8F6E;&#x5ED3;&#x5750;&#x6807;&#x70B9;
contourIdx ,&#x8F6E;&#x5ED3;&#x987A;&#x5E8F;&#x53F7;  -1&#x8868;&#x793A;&#x7ED8;&#x5236;&#x6240;&#x6709;&#x8F6E;&#x5ED3;
color&#xFF1A;&#x989C;&#x8272;&#xFF0C;&#xFF08;0&#xFF0C;0&#xFF0C;255&#xFF09;
thickness&#xFF1A;&#x7EBF;&#x5BBD;&#xFF0C;-1&#x662F;&#x5168;&#x90E8;&#x586B;&#x5145;

代码:

import cv2
import numpy as np

def start():
    img = cv2.imread('C:\\Users\\Zz\\Pictures\\3.png')
    #&#x8F6C;&#x6362;&#x6210;&#x7070;&#x5EA6;
    imggray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
    #&#x4E8C;&#x503C;&#x5316;
    ret,binary = cv2.threshold(imggray,150,255,cv2.THRESH_BINARY)
    #&#x8F6E;&#x5ED3;&#x67E5;&#x627E;
    contours,hierarchy = cv2.findContours(binary,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
    #&#x7ED8;&#x5236;&#x8FB9;
    cv2.drawContours(img, contours,-1,(0,0,255),5)

    cv2.imshow('lines',img)

    cv2.waitKey(0)

if __name__ == '__main__':
    start()

效果:

python opencv图像笔记

轮廓的面积与周长

轮廓面积API:

contourArea(contour)
contour:&#x8F6E;&#x5ED3;

轮廓周长API:

arcLength(curve,closed)
curve:&#x8F6E;&#x5ED3;
closed:&#x662F;&#x5426;&#x662F;&#x95ED;&#x5408;&#x7684;&#x8F6E;&#x5ED3;

代码:

import cv2
import numpy as np

def start():
    img = cv2.imread('C:\\Users\\Zz\\Pictures\\3.png')
    #&#x8F6C;&#x6362;&#x6210;&#x7070;&#x5EA6;
    imggray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
    #&#x4E8C;&#x503C;&#x5316;
    ret,binary = cv2.threshold(imggray,150,255,cv2.THRESH_BINARY)
    #&#x8F6E;&#x5ED3;&#x67E5;&#x627E;
    contours,hierarchy = cv2.findContours(binary,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
    #&#x7ED8;&#x5236;&#x8FB9;
    cv2.drawContours(img, contours,-1,(0,0,255),5)
    #&#x8BA1;&#x7B97;&#x9762;&#x79EF;
    area = cv2.contourArea(contours[0])
    #&#x8BA1;&#x7B97;&#x5468;&#x957F;
    len = cv2.arcLength(contours[0],True)
    print("area=%d"%(area))
    print("len=%d" % (len))
    cv2.imshow('lines',img)

    cv2.waitKey(0)

if __name__ == '__main__':
    start()

输出:

python opencv图像笔记

多边形逼近与凸包

python opencv图像笔记
多边形逼近API
approxPolyDP(curve,epsilon,closed)
curve:&#x8F6E;&#x5ED3;
epsilon:&#x7CBE;&#x5EA6;
closed:&#x662F;&#x5426;&#x662F;&#x95ED;&#x5408;&#x8F6E;&#x5ED3;

凸包API:

convexHull(point,clockwise,...)
points:&#x8F6E;&#x5ED3;
clockwise:&#x987A;&#x65F6;&#x9488;&#x7ED8;&#x5236;

代码:

import cv2
import numpy as np

def drawShape(src,points):
    i=0
    while i<len(points): if(i="=len(points)-1):" x,y="points[i][0]" x1 ,y1="points[0][0]" cv2.line(src, (x, y), (x1, y1), (0, 0, 225), 3) else: x1,y1="points[i+1][0]" cv2.line(src,(x,y),(x1,y1),(0,0,225),3) i="i+1" def start(): img="cv2.imread('C:\\Users\\Zz\\Pictures\\hand.jpg')" #转换成灰度 imggray="cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)" #二值化 ret,binary="cv2.threshold(imggray,210,255,cv2.THRESH_BINARY)" #轮廓查找 contours,hierarchy="cv2.findContours(binary,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)" #绘制边 cv2.drawcontours(img, contours,-1,(0,255,255),5) e="20" approx="cv2.approxPolyDP(contours[1],e,True)" drawshape(img,approx) cv2.imshow('lines',img) cv2.waitkey(0) if __name__="=" '__main__': start() < code></len(points):>

效果图:

python opencv图像笔记
凸包:
代码:
 full = cv2.convexHull(contours[1])
    drawShape(img,full)

效果图:

python opencv图像笔记

外接矩形

  • 最小外接矩形
  • 最大外接矩形
    python opencv图像笔记
    最小外接矩形API
minAreaRect(points)
points:&#x8F6E;&#x5ED3;
&#x8FD4;&#x56DE;&#x503C;&#xFF1A;RotatedRect &#x89D2;&#x5EA6;

RotatedRect

  • x,y
  • width,height
  • angle
    最大外接矩形API
boundingRect(array)
array:&#x8F6E;&#x5ED3;
&#x8FD4;&#x56DE;&#x503C;&#xFF1A;Rect &#xFF08;&#x5305;&#x62EC;&#x8D77;&#x59CB;&#x70B9;&#xFF0C;&#x5BBD;&#x548C;&#x9AD8;&#xFF09;

代码:

import cv2
import numpy as np

def start():
    img = cv2.imread('C:\\Users\\Zz\\Pictures\\hello.png')
    # &#x8F6C;&#x6362;&#x6210;&#x7070;&#x5EA6;
    imggray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    # &#x4E8C;&#x503C;&#x5316;
    ret, binary = cv2.threshold(imggray, 210, 255, cv2.THRESH_BINARY)
    # &#x8F6E;&#x5ED3;&#x67E5;&#x627E;
    contours, hierarchy = cv2.findContours(binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

    #&#x6700;&#x5C0F;&#x5916;&#x63A5;&#x77E9;&#x5F62;
    r=cv2.minAreaRect(contours[1])
    box= cv2.boxPoints(r)  #&#x53EA;&#x53D6;&#x8D77;&#x59CB;&#x70B9;&#x548C;&#x5BBD;&#x9AD8;
    #&#x5F3A;&#x5236;&#x8F6C;&#x6362; &#x6D6E;&#x70B9;&#x578B;&#x8F6C;&#x6362;&#x4E3A;int
    box=np.int0(box)
    cv2.drawContours(img,[box],0,(0,225,0),2)

    #&#x6700;&#x5927;&#x5916;&#x63A5;&#x77E9;&#x5F62;
    x,y,w,h=cv2.boundingRect(contours[1])

    cv2.rectangle(img,(x,y),(x+w,y+h),(225,0,0),2)

    cv2.imshow('lines', img)

    cv2.waitKey(0)

if __name__ == '__main__':
    start()

效果:

python opencv图像笔记

实战车辆统计

第一步,读取视频

import cv2
import numpy as np

def start():
    #&#x6253;&#x5F00;&#x89C6;&#x9891;
    cap= cv2.VideoCapture("C:\\Users\\Zz\\Videos\\1.mp4")

    #&#x4E00;&#x5E27;&#x4E00;&#x5E27;&#x8BFB;&#x53D6;
    while True:
        ret,frame =cap.read()
        if ret:
            #&#x663E;&#x793A;&#x753B;&#x9762;
            cv2.imshow("video",frame)

        key=cv2.waitKey(10)
        #esc&#x6309;&#x952E;
        if (key==27):
            break

    cap.release()
    cv2.destroyAllWindows()

if __name__ == '__main__':
    start()

去除背景

将前景提取,去除背景
API

createBackgroundSubractorMOG(...)
history=200   #200ms&#x662F;5&#x5E27;

论文推荐
An improved adaptive background mixture model for real-time tracking with shadow detection

代码:

import cv2
import numpy as np

def start():
    #&#x6253;&#x5F00;&#x89C6;&#x9891;
    cap= cv2.VideoCapture("C:\\Users\\Zz\\Videos\\1.mp4")

    #&#x83B7;&#x53D6;&#x53BB;&#x80CC;&#x666F;&#x5BF9;&#x8C61;
    bgsubmog = cv2.bgsegm.createBackgroundSubtractorMOG()

    #&#x4E00;&#x5E27;&#x4E00;&#x5E27;&#x8BFB;&#x53D6;
    while True:
        ret,frame =cap.read()
        if ret:

            #&#x7070;&#x5EA6;
            cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)
            #&#x53BB;&#x9AD8;&#x65AF;&#x566A;&#x70B9;
            blur= cv2.GaussianBlur(frame,(3,3),5)
            #&#x53D6;&#x80CC;&#x5F71;
            mask=bgsubmog.apply(blur)

            #&#x663E;&#x793A;&#x753B;&#x9762;
            cv2.imshow("video",mask)

        key=cv2.waitKey(10)
        #esc&#x6309;&#x952E;
        if (key==27):
            break

    #&#x6D88;&#x9664;&#x8D44;&#x6E90;
    cap.release()
    cv2.destroyAllWindows()

if __name__ == '__main__':
    start()

效果:

python opencv图像笔记

形态处理

代码:

import cv2
import numpy as np

def start():
    #&#x6253;&#x5F00;&#x89C6;&#x9891;
    cap= cv2.VideoCapture("C:\\Users\\Zz\\Videos\\1.mp4")

    #&#x83B7;&#x53D6;&#x53BB;&#x80CC;&#x666F;&#x5BF9;&#x8C61;
    bgsubmog = cv2.bgsegm.createBackgroundSubtractorMOG()

    #&#x4E00;&#x5E27;&#x4E00;&#x5E27;&#x8BFB;&#x53D6;
    while True:
        ret,frame =cap.read()
        if ret:

            #&#x7070;&#x5EA6;
            img = cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)
            #&#x53BB;&#x9AD8;&#x65AF;&#x566A;&#x70B9;
            blur= cv2.GaussianBlur(img,(3,3),5)
            #&#x53BB;&#x6389;&#x80CC;&#x666F;
            mask=bgsubmog.apply(blur)

            #&#x8150;&#x8680; &#x53BB;&#x6389;&#x5C0F;&#x7684;&#x7684;&#x7269;&#x4F53;
            kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
            erode = cv2.erode(mask,kernel,iterations=1)
            #&#x81A8;&#x80C0; &#x8FD8;&#x539F;&#x653E;&#x5927;
            dilate = cv2.dilate(erode,kernel,iterations=3)
            #&#x95ED;&#x8FD0;&#x7B97; &#x53BB;&#x6389;&#x4E2D;&#x95F4;&#x7684;&#x7A7A;&#x7F3A;
            close = cv2.morphologyEx(dilate,cv2.MORPH_CLOSE,kernel)
            close = cv2.morphologyEx(dilate, cv2.MORPH_CLOSE, kernel)

            #&#x67E5;&#x627E;&#x8F6E;&#x5ED3;
            contours,hierarchy = cv2.findContours(close,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)

            for (i,con) in enumerate(contours):
                #&#x83B7;&#x53D6;&#x6700;&#x5927;&#x5916;&#x63A5;&#x77E9;&#x5F62;
                (x,y,w,h)=cv2.boundingRect(con)
                #&#x7ED8;&#x5236;&#x77E9;&#x5F62;
                cv2.rectangle(frame,(x,y),(x+w,y+h),(0,0,225),2)

            #&#x663E;&#x793A;&#x753B;&#x9762;
            cv2.imshow("video", frame)
        key=cv2.waitKey(10)
        #esc&#x6309;&#x952E;
        if (key==27):
            break

    #&#x6D88;&#x9664;&#x8D44;&#x6E90;
    cap.release()
    cv2.destroyAllWindows()

if __name__ == '__main__':
    start()

效果:

python opencv图像笔记

车辆统计

代码:

import cv2
import numpy as np

min_w=30
min_h=30

#&#x68C0;&#x6D4B;&#x7EBF;&#x7684;&#x9AD8;&#x5EA6;
line_hight = 1100
#&#x5B58;&#x653E;&#x8F66;&#x8F86;&#x6709;&#x6548;&#x6570;&#x7EC4;
cars=[]
#&#x7EBF;&#x7684;&#x504F;&#x79FB;&#x91CF;
offset=6

#&#x6C42;&#x4E2D;&#x5FC3;&#x70B9;
def center(x,y,w,h):
     x1=int(w/2)
    y1=int(h/2)
    cx=x+x1
    cy=y+y1
    return cx,cy

def start():
    # &#x8DEF;&#x8FC7;&#x8F66;&#x7684;&#x6570;&#x91CF;
    carnum = 0
    #&#x6253;&#x5F00;&#x89C6;&#x9891;
    cap= cv2.VideoCapture("C:\\Users\\Zz\\Videos\\1.mp4")
    #&#x83B7;&#x53D6;&#x53BB;&#x80CC;&#x666F;&#x5BF9;&#x8C61;
    bgsubmog = cv2.bgsegm.createBackgroundSubtractorMOG()

    #&#x4E00;&#x5E27;&#x4E00;&#x5E27;&#x8BFB;&#x53D6;
    while True:
        ret,frame =cap.read()

        if ret:

            #&#x7070;&#x5EA6;
            img = cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)
            #&#x53BB;&#x9AD8;&#x65AF;&#x566A;&#x70B9;
            blur= cv2.GaussianBlur(img,(3,3),5)
            #&#x53BB;&#x6389;&#x80CC;&#x666F;
            mask=bgsubmog.apply(blur)

            #&#x8150;&#x8680; &#x53BB;&#x6389;&#x5C0F;&#x7684;&#x7684;&#x7269;&#x4F53;
            kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
            erode = cv2.erode(mask,kernel,iterations=1)
            #&#x81A8;&#x80C0; &#x8FD8;&#x539F;&#x653E;&#x5927;
            dilate = cv2.dilate(erode,kernel,iterations=3)
            #&#x95ED;&#x8FD0;&#x7B97; &#x53BB;&#x6389;&#x4E2D;&#x95F4;&#x7684;&#x7A7A;&#x7F3A;
            close = cv2.morphologyEx(dilate,cv2.MORPH_CLOSE,kernel)
            close = cv2.morphologyEx(dilate, cv2.MORPH_CLOSE, kernel)

            #&#x67E5;&#x627E;&#x8F6E;&#x5ED3;
            contours,hierarchy = cv2.findContours(close,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)

            cv2.line(frame,(line_hight,10),(line_hight,710),(255,255,0),3)
            for (i,con) in enumerate(contours):

                #&#x83B7;&#x53D6;&#x6700;&#x5927;&#x5916;&#x63A5;&#x77E9;&#x5F62;
                (x,y,w,h)=cv2.boundingRect(con)

                #&#x5BF9;&#x8F66;&#x5BBD;&#x9AD8;&#x6BD4;&#x8FDB;&#x884C;&#x5224;&#x65AD;
                #&#x9A8C;&#x8BC1;&#x8F66;&#x662F;&#x5426;&#x6709;&#x6548;
                isValid=(w>=min_w) and (h >=min_h)
                if(not  isValid):
                    continue
                # &#x7ED8;&#x5236;&#x77E9;&#x5F62;
                cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 0, 225), 2)
                #&#x5C06;&#x6709;&#x7528;&#x7684;&#x8F66;&#x4E2D;&#x5FC3;&#x70B9;&#x653E;&#x5165;&#x96C6;&#x5408;
                cpoint = center(x,y,w,h)
                cars.append(cpoint)

                for(x,y) in cars:
                    if(x>line_hight-offset) and(x<line_hight+offset): carnum="carnum+1" #从有用数组移除 cars.remove((x,y)) print(carnum) #显示画面 cv2.imshow("video", frame) key="cv2.waitKey(10)" #esc按键 if (key="=27):" break #消除资源 cap.release() cv2.destroyallwindows() __name__="=" '__main__': start() < code></line_hight+offset):>

效果:

python opencv图像笔记

opencv特征检测

什么是特征
图像特征就是指有意义区域
具有独特性、易于识别性,比如角点、斑点以及高密度区
角点
在特征中最重要的是角点
灰度梯度的最大值对应的像素
两条线的交点
极值点(一阶导数最大,但二阶导数为0)

Harris 角点

python opencv图像笔记
  • 光滑地区,无论向哪里移动,衡量系数不变
  • 边缘地址,垂直边缘移动时,衡量系数变化剧烈
  • 在交点处,往那个方向移动,衡量系统都变化剧烈

Harris角点检测API

cornerHarris(img,dst,blockSize,ksize,k)
dst &#x8F93;&#x51FA;&#x7ED3;&#x679C;&#xFF08;python&#x6CA1;&#x6709;&#xFF09;
blockSize:&#x68C0;&#x6D4B;&#x7A97;&#x53E3;&#x5927;&#x5C0F; &#x7A97;&#x53E3;&#x8D8A;&#x5927;&#xFF0C;&#x68C0;&#x6D4B;&#x654F;&#x611F;&#x8D8A;&#x9AD8;
ksize&#xFF1A;Sobel&#x7684;&#x5377;&#x79EF;&#x6838;
k&#xFF1A;&#x6743;&#x91CD;&#x7CFB;&#x6570;&#xFF0C;&#x7ECF;&#x9A8C;&#x503C;&#xFF0C;&#x4E00;&#x822C;&#x53D6; 0.0.2~0.04&#x4E4B;&#x95F4;

代码:

import cv2
import numpy as np

def start():
    img = cv2.imread('C:\\Users\\Zz\\Pictures\\shudu.png')

    #&#x7070;&#x5EA6;&#x5316;
    grayimg=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
    #Harris&#x89D2;&#x70B9;&#x68C0;&#x6D4B;
    dst =cv2.cornerHarris(grayimg,2,3,0.04)

    #Harris&#x89D2;&#x70B9;&#x5C55;&#x793A;
    img[dst>0.01*dst.max()]=[0,0,255]

    cv2.imshow("Harris",img)
    cv2.waitKey(0)

if __name__ == '__main__':
    start()

效果:

python opencv图像笔记

Shi-Tomasi角点检测

  • Shi-Tomasi是Harris角点检测的改进
  • Harris角点检测算的稳定性和k有关,而k是一个经验值,不好设定最佳值

Shi-Tomasi角点检测API

goodFeaturesTrack(img,maxCorners,...)
maxCorners:&#x89D2;&#x70B9;&#x7684;&#x6700;&#x5927;&#x6570;&#xFF0C;&#x503C;&#x4E3A;0&#x8868;&#x793A;&#x65E0;&#x9650;&#x5236;
qualityLevel&#xFF1A;&#x5C0F;&#x4E8E;1.0&#x7684;&#x6B63;&#x6570;&#xFF0C;&#x4E00;&#x822C;&#x5728;0.01-0.1&#x4E4B;&#x95F4;
minDistance&#xFF1A;&#x89D2;&#x4E4B;&#x95F4;&#x7684;&#x6700;&#x5C0F;&#x6B27;&#x5F0F;&#x8DDD;&#x79BB;&#xFF0C;&#x5FFD;&#x7565;&#x5C0F;&#x4E8E;&#x6B64;&#x8DDD;&#x79BB;&#x7684;&#x70B9; &#x8DDD;&#x79BB;&#x8D8A;&#x5927;&#x68C0;&#x6D4B;&#x7684;&#x89D2;&#x8D8A;&#x5C11;
mask&#xFF1A;&#x611F;&#x5174;&#x8DA3;&#x7684;&#x533A;&#x57DF;
blockSize&#xFF1A;&#x68C0;&#x6D4B;&#x7A97;&#x53E3;
useHarrisDetector&#xFF1A;&#x662F;&#x5426;&#x4F7F;&#x7528;Harris&#x7B97;&#x6CD5;
k:&#x9ED8;&#x8BA4;&#x662F;0.04

代码:

import cv2
import numpy as np

def start():
    img = cv2.imread('C:\\Users\\Zz\\Pictures\\shudu.png')

    #&#x7070;&#x5EA6;&#x5316;
    grayimg=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
    #Harris&#x89D2;&#x70B9;&#x68C0;&#x6D4B;
    #dst =cv2.cornerHarris(grayimg,2,3,0.04)

    corner=cv2.goodFeaturesToTrack(grayimg,1000,0.01,10)

    #Harris&#x89D2;&#x70B9;&#x5C55;&#x793A;
    #img[dst>0.01*dst.max()]=[0,0,255]
    #&#x6D6E;&#x70B9;&#x578B;&#x8F6C;&#x6362;&#x6210;&#x6574;&#x578B;
    corner =np.int0(corner)
    for i in corner:
        x,y=i.ravel()
        cv2.circle(img,(x,y),3,(255,0,0),-1)

    cv2.imshow("Harris",img)
    cv2.waitKey(0)

if __name__ == '__main__':
    start()

效果:

python opencv图像笔记

SIFT关键点检测(Scale-Invariant Feature Transform)

  • Harris角点具有旋转不变的特征
  • 但缩放后,原来的角有可能就不是角点了

python opencv图像笔记

步骤

  1. 创建SIFT对象
  2. 进行检测,kp=sift.detect(img,…)
  3. 绘制关键点,drawKeypoints(gray,kp,img)

代码:

import cv2
import numpy as np

def start():
    img = cv2.imread('C:\\Users\\Zz\\Pictures\\shudu.png')
    gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

    sift=cv2.xfeatures2d.SIFT_create()
    kp= sift.detect(gray,None)

    #&#x7ED8;&#x5236;&#x70B9;
    cv2.drawKeypoints(gray,kp,img)

    cv2.imshow("img",img)
    cv2.waitKey(0)

if __name__ == '__main__':
    start()

效果:

python opencv图像笔记

SIFT计算描述子

关键点和描述子

  • 关键点:位置、大小和方向
  • 关键点描述子:记录了关键点周围对其有贡献的像素点的一组向量值,其不受仿射变换、光照变换等影响

计算描述子

  • kp,des=sift.compute(img,kp)
  • 其作用是进行特征匹配

同时计算关键点和描述

  • kp,des=sift.detectAndCompute(img,…)
  • mask:指明对img中哪个区域进行计算

代码:

import cv2
import numpy as np

def start():
    img = cv2.imread('C:\\Users\\Zz\\Pictures\\shudu.png')
    gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

    #&#x521B;&#x5EFA;sift&#x5BF9;&#x8C61;
    sift=cv2.xfeatures2d.SIFT_create()
    #&#x8FDB;&#x884C;&#x68C0;&#x6D4B;
    kp,des= sift.detectAndCompute(gray,None)

    print(des)

    #&#x7ED8;&#x5236;&#x70B9;
    cv2.drawKeypoints(gray,kp,img)

    cv2.imshow("img",img)
    cv2.waitKey(0)

if __name__ == '__main__':
    start()

效果:

python opencv图像笔记

SURF (Speeded-Up Robust Features)

SIFT最大的问题是速度慢,因此才有SURF
使用步骤

  1. surf=cv2.xfeatures2d.SURF_create()
  2. kp,des=surf.detectAndCompute(img,mask)

代码:

import cv2
import numpy as np

def start():
    img = cv2.imread('C:\\Users\\Zz\\Pictures\\shudu.png')
    gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

    #&#x521B;&#x5EFA;surf&#x5BF9;&#x8C61;
    surf = cv2.xfeatures2d.SURF_create()
    #&#x8FDB;&#x884C;&#x68C0;&#x6D4B;
    kp,des= surf.detectAndCompute(gray,None)

    #print(des)

    #&#x7ED8;&#x5236;&#x70B9;
    cv2.drawKeypoints(gray,kp,img)

    cv2.imshow("img",img)
    cv2.waitKey(0)

if __name__ == '__main__':
    start()

运行效果:
因为版权opencv4,不能使用!!!!!我超!!

ORB (Oriented FAST and Rotated BRIEF)

ORB可以做到实时检测
ORB = Oriented FAST+Rotated BRIEF
使用步骤

  1. orb=cv2.ORB_create()
  2. kp,des=orb.detectAndCompute(img,mask)

代码:

import cv2
import numpy as np

def start():
    img = cv2.imread('C:\\Users\\Zz\\Pictures\\shudu.png')
    gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

    #&#x521B;&#x5EFA;ORB&#x5BF9;&#x8C61;
    orb=cv2.ORB_create()
    #&#x8FDB;&#x884C;&#x68C0;&#x6D4B;
    kp,des= orb.detectAndCompute(gray,None)

    #print(des)

    #&#x7ED8;&#x5236;&#x70B9;
    cv2.drawKeypoints(gray,kp,img)
    #&#x56E0;&#x4E3A;&#x7248;&#x6743;&#xFF0C;&#x6211;&#x8D85;&#xFF0C;&#x4E0D;&#x80FD;&#x7528;&#xFF01;&#xFF01;&#xFF01;&#xFF01;
    cv2.imshow("img",img)
    cv2.waitKey(0)

if __name__ == '__main__':
    start()

效果:

python opencv图像笔记

暴力特征匹配

特征匹配方法:

  • BF(Brute-Force),暴力特征匹配方法
  • FLANN 最快邻近区特征匹配方法
    暴力特征匹配原理
    它使用第一组中每个特征的描述子
    与第二组中的所有特征描述子进行匹配
    计算他们之间的差距,然后将最接近一个匹配返回

opencv特征匹配步骤

  1. 创建匹配器,BFMatcher(normType,crossCheck)
  2. 进行特征匹配,bf.match(des1,des2)
  3. 绘制匹配点,cv2.drawMatches(img1,kp1,img2,k2,…)

BFMatcher

  • normType:NORM_L1,NORM_L2,HAMMING1…(默认值NORM_L2)
  • crossCheck:是否进行交叉匹配,默认为false(开启了计算量大)

match方法

  • 参数为SIFT、SURF、OBR等计算的描述子
  • 对两幅图的描述子进行计算

drawMatches

  • 搜索img,kp
  • 匹配图img,kp
  • match()方法返回的匹配结果
    代码:
import cv2
import numpy as np

def start():
    img1 = cv2.imread('C:\\Users\\Zz\\Pictures\\bf1.jpg')
    img2 = cv2.imread('C:\\Users\\Zz\\Pictures\\bf2.jpg')

    gray1 = cv2.cvtColor(img1,cv2.COLOR_BGR2GRAY)
    gray2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)

    # &#x521B;&#x5EFA;sift&#x5BF9;&#x8C61;
    sift = cv2.xfeatures2d.SIFT_create()
    #&#x8FDB;&#x884C;&#x68C0;&#x6D4B;
    kp1,des1= sift.detectAndCompute(gray1,None)
    kp2, des2 = sift.detectAndCompute(gray2, None)

    bf=cv2.BFMatcher(cv2.NORM_L1)
    match= bf.match(des1,des2)

    #&#x7ED8;&#x5236;&#x70B9;
    img3= cv2.drawMatches(img1,kp1,img2,kp2,match,None)
    #print(des)

    cv2.imshow("img",img3)
    cv2.waitKey(0)

if __name__ == '__main__':
    start()

效果:

python opencv图像笔记

FLANN特征匹配

  • 在进行批量特征匹配时,FLANN速度更快
  • 由于它使用的时邻近近似值,所以精度比较差

使用FLANN特征匹配的步骤

  • 创建FLANN匹配器,FLannBasedMatcher(…)
  • 进行特征匹配,flann.match/knnMatch(…)
  • 绘制匹配点,cv2.drawMatches/drawMatchesKnn(…)

FlannBasedMatcher

  • index_params字典:匹配算法KDTREE(SIFT、SURF)、LSH(ORD)
  • search——params字典:指定KDTREE算法中遍历树的次数(一般设置为5)

KDTREE
index_params=dict(algorithm=FLANN_INDEX_KDTREE,trees=5)
algorithm=FLANN_INDEX_KDTREE实际上是1

search_params

  • search_params = dict(checks=50)

knnMatch方法

  • 参数为SIFT、SURF、ORB等计算的描述子
  • k,表示取欧式距离最近的前k个关键点
  • 返回的是匹配结果DMatch对象

DMatch的内容

  • distance,描述子之间的距离,值越低越好
  • queryIdx,第一个图像的描述子索引值
  • trainIdx,第二个图的描述子索引值
  • imgIdx,第二个图的索引值

drawMatchesKnn

  • 搜索img,kp
  • 匹配图img,kp
  • match()方法返回的匹配值

代码:

import cv2
import numpy as np

def start():

    img1 = cv2.imread('C:\\Users\\Zz\\Pictures\\bf2.jpg')
    img2 = cv2.imread('C:\\Users\\Zz\\Pictures\\bf1.jpg')

    gray1 = cv2.cvtColor(img1,cv2.COLOR_BGR2GRAY)
    gray2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)

    # &#x521B;&#x5EFA;sift&#x5BF9;&#x8C61;
    sift = cv2.xfeatures2d.SIFT_create()
    #&#x8FDB;&#x884C;&#x68C0;&#x6D4B;
    kp1,des1= sift.detectAndCompute(gray1,None)
    kp2, des2 = sift.detectAndCompute(gray2, None)
    # &#x7279;&#x5F81;&#x68C0;&#x6D4B;&#x5668;
    index_params = dict(algorithm=1, trees=5)
    search_params = dict(checks=50)
    flann= cv2.FlannBasedMatcher(index_params,search_params)

    #&#x5BF9;&#x63CF;&#x8FF0;&#x5B50;&#x8FDB;&#x884C;&#x5339;&#x914D;&#x8BA1;&#x7B97;
    matchs= flann.knnMatch(des1,des2,k=2)

    good=[]
    for i,(m,n) in enumerate(matchs):
        if m.distance < 0.7*n.distance:
            good.append(m)

    ret = cv2.drawMatchesKnn(img1,kp1,img2,kp2,[good],None)
    cv2.imshow("img",ret)
    cv2.waitKey(0)

if __name__ == '__main__':
    start()

效果:

python opencv图像笔记

图像查找

特征匹配+单应性矩阵

python opencv图像笔记
代码:
import cv2
import numpy as np

def start():
    img1 = cv2.imread('C:\\Users\\Zz\\Pictures\\bf2.jpg')
    img2 = cv2.imread('C:\\Users\\Zz\\Pictures\\bf1.jpg')

    gray1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
    gray2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)

    # &#x521B;&#x5EFA;sift&#x5BF9;&#x8C61;
    sift = cv2.xfeatures2d.SIFT_create()
    # &#x8FDB;&#x884C;&#x68C0;&#x6D4B;
    kp1, des1 = sift.detectAndCompute(gray1, None)
    kp2, des2 = sift.detectAndCompute(gray2, None)
    # &#x7279;&#x5F81;&#x68C0;&#x6D4B;&#x5668;
    index_params = dict(algorithm=1, trees=5)
    search_params = dict(checks=50)
    flann = cv2.FlannBasedMatcher(index_params, search_params)

    # &#x5BF9;&#x63CF;&#x8FF0;&#x5B50;&#x8FDB;&#x884C;&#x5339;&#x914D;&#x8BA1;&#x7B97;
    matchs = flann.knnMatch(des1, des2, k=2)

    good = []
    for i, (m, n) in enumerate(matchs):
        if m.distance < 0.7 * n.distance:
            good.append(m)

    if len(good)>=4:
        #&#x83B7;&#x53D6;&#x5339;&#x914D;&#x70B9;
        srcPts =  np.float32( [kp1[m.queryIdx].pt for m in good]).reshape(-1,1,2)
        dstPts = np.float32([kp2[m.trainIdx].pt for m in good]).reshape(-1, 1, 2)
        #&#x67E5;&#x627E;&#x5355;&#x5143;&#x77E9;&#x9635;
        H,_= cv2.findHomography(srcPts,dstPts,cv2.RANSAC,5.0)
        #&#x900F;&#x89C6;&#x53D8;&#x6362;
        h,w=img1.shape[:2]
        pts = np.float32([[0,0],[0,h-1],[w-1,h-1],[w-1,0]]).reshape(-1,1,2)
        dst=cv2.perspectiveTransform(pts,H)
        cv2.polylines(img2,[np.int32(dst)],True,(0,0,255))
    else:
        print("the num is less than 4")
        exit()

    ret = cv2.drawMatchesKnn(img1, kp1, img2, kp2, [good], None)
    cv2.imshow("img",ret)
    cv2.waitKey(0)

if __name__ == '__main__':
    start()

效果:

python opencv图像笔记

Original: https://blog.csdn.net/q327192368/article/details/125585415
Author: 一天发火两次
Title: python opencv图像笔记

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/703977/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球