本文主要针对opencv的python版本进行记录
由于opencv比较大,并且anaconda方便管理库,采用清华的镜像安装(好像清华镜像又能够使用了)
1.安装anaconda
2.打开anaconda prompt,添加清华镜像
onda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/
conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main/
conda config --set show_channel_urls yes
添加完成之后就开始安装opencv,我们可以通过下面的命令让环境自动选择opencv版本
conda install -c menpo opencv
之后就可以使用了
读取一张图片并显示出来,代码如下:
import cv2 as cv
src = cv.imread('d:/shili.jpg',1)
cv.imshow("chuangkou", src)
cv.waitKey(0)
cv.destroyAllWindows()
1、参数说明,imread(),传入两个参数,第一个参数文件的路径,要是文件和图片在同一个路径,可以只用给出图片的名称就可以。第二个参数,图片的读取方式,0,灰度图像,1,彩色图像。
2、imshow(),同样两个参数,第一个参数,显示窗口的名称,第二个参数,要显示的图片。
3、cv2.nameWindows(‘image’, cv2.WINDOWS_NORMAL/WINDOW_AUTOSIZE)函数作用就是可以调整显示图片窗口的大小,里面可传入两个参数,一个是窗口的名称,另一个是正常或者自动调整的窗口
4、waitKey()与waitKey(0),都代表无限等待,waitKey函数的默认参数就是int delay = 0,故这俩形式本质是一样的,按下键盘的任意键就会关闭窗口。当里面的数字大于零时,会等待若干毫秒执行下面的步骤,用在视频中就会选择截取每一帧的图片,在imshow(),后面加上这个函数,表示图像一直显示,不然无法显示图片,同时他会返回按键的ascii码,他的使用我们可以通过代码来理解。
import cv2
img = cv2.imread('shili.jpg',1)
cv2.imshow('image',img)
k = cv2.waitKey(0)
if k == 27: # wait for ESC key to exit
cv2.destroyAllWindows()
elif k == ord('s'): # wait for 's' key to save and exit
cv2.imwrite('messigray.png',img)
cv2.destroyAllWindows()
这个程序的表示的是在按下esc时候,直接关闭窗口,当按下esc时候,这个waitkey()函数返回的是27给k,执行退出。
代码如下
#coding:utf-8
import cv2
import numpy as np
#输出图片的属性
def get_image_info(image):
print(type(image)) # 显示图片的类型,numpy数据类型
"""
shape属性表示图像的大小,shape会返回tuple元组,
第一个元素是矩阵行数,第二个列数,第三个通道数
"""
print(image.shape)
print(image.size) # 图像大小
print(image.dtype) # 图像类型
pixel_data = np.array(image)
print(pixel_data) # 图片矩阵
src = cv2.imread('shili.jpg', 1)
cv2.namedWindow('1', cv2.WINDOW_NORMAL)
cv2.imshow('1', src)
get_image_info(src)
cv2.imwrite('baocun2.png',src)
cv2.waitKey(0)
cv2.destroyAllWindows()
这个函数的输出如下图所示:
(363, 552, 3)
601128
uint8
[[[ 87 125 129]
[ 97 138 141]
[ 90 131 134]
...
[228 176 135]
[ 14 5 0]
[ 0 2 2]]
[[ 80 117 121]
[ 96 134 138]
[ 87 128 131]
...
[228 176 135]
[ 14 5 0]
[ 0 2 2]]
[[108 143 147]
[117 154 158]
[100 138 142]
...
[228 176 135]
[ 14 5 0]
[ 0 2 2]]
...
[[216 220 225]
[216 220 225]
[216 220 225]
...
[196 209 217]
[ 0 0 4]
[ 0 0 3]]
[[212 216 221]
[213 217 222]
[213 217 222]
...
[198 211 219]
[ 0 3 7]
[ 0 0 3]]
[[212 216 221]
[212 216 221]
[212 216 221]
...
[194 207 215]
[ 0 0 4]
[ 0 0 3]]]
Process finished with exit code 0
看完这个记过知道啥意思了吧,最后图片的输出是三通道,每一列向量是一个通道,一共363行,552列。
代码如下:
#coding:utf-8
# 打开摄像头,获取图片
import cv2
def video_demo():
captuer = cv2.VideoCapture(0) #打开摄像头,0代表的是设备id,如通有多个摄像头,可以设置其他数值
while True:
ret, frame = captuer.read() #读取摄像头,他能返回两个参数
frame = cv2.flip(frame, 1) #0,上下翻转,1左右翻转
cv2.imshow("video", frame)
if cv2.waitKey(10) &0xFF == ord('q'): #按q关闭摄像头
break
video_demo()
cv2.destroyAllWindows()
其中ret, frame是读取视频返回的两个值,其中ret是布尔值,如果读取帧是正确的则返回True,如果文件读取到结尾,它的返回值就为False。frame就是每一帧的图像,是个三维矩阵。
cv2.flip(frame, 1),第二个参数主要有1,0,-1,代表水平翻转,垂直翻转,水平垂直翻转。
5.1读取一张图片,修改颜色通道,后输出
可以得到图像的行数,列数,通道数举证,对矩阵进行操作可改变图像像素。
# -*- coding=utf-8 -*-
import numpy as np
import cv2
#numpy数字操作
def access_pixles(image):
print(image.shape)
height = image.shape[0]
width = image.shape[1]
channel = image.shape[2]
print("width : %s, height : %s, channel : %s" % (width, height, channel))
for row in range(height):
for col in range(width):
for c in range(channel):
pv = image[row, col, c]
image[row, col, c] = 255 - pv
cv2.imshow("修改后的照片", image)
src = cv2.imread("shili.jpg", 1)
cv2.imshow("原来", src)
t1 = cv2.getTickCount()
access_pixles(src)
t2 = cv2.getTickCount()
time = (t2-t1)*1000/cv2.getTickFrequency()
print("time: %s" % time)
cv2.waitKey(0)
cv2.destroyAllWindows()
输出结果
(363, 552, 3)
width : 552, height : 363, channel : 3
time: 1183.3025
可以看到要是改为英文就不会乱码,先这么凑合着看
我们一起来理解下代码
image[row, col, c],获取像素点值,image[row, col, c] = 255 - pv,像素取反
计算时间的有两个模块,一个是time,另一个是opencv自带的cv2.getTickCount(), getTickCount():用于返回从操作系统启动到当前所经的计时周期数,看名字也很好理解,get Tick Count(s)。
getTickFrequency():用于返回CPU的频率。get Tick Frequency。这里的单位是秒,也就是一秒内重复的次数,多少个周期每秒。
所以剩下的就很清晰了:
总次数/一秒内重复的次数 = 时间(s)
1000 *总次数/一秒内重复的次数= 时间(ms)
这个逻辑很清晰,没什么问题,但是这里有一个小坑,那就是C版本的cvGetTickFrequency()函数和C++版本的getTickFrequency()的单位不一样,前者以ms计算频率,后者以s为单位计算频率,所以如果使用C版本的cvGetTickFrequency()计算时间的话,应该是:
总次数/一秒内重复的次数1000 = 时间(ms)
总次数/一秒内重复的次数1000000
用到函数zeros和ones,代码如下
# coding :utf-8
import cv2
import numpy as np
def creat_image():
img = np.zeros([400, 400, 3],np.uint8) # zeros: double类零矩阵,创建400*400,3通道的矩阵图像,像素格式为nint8
img[:, :, 0] = np.ones([400, 400])*255 # ones([400, 400])是创建一个400*400的全一矩阵,后面*255变为全部255的矩阵,并将这个矩阵的值赋值给img的第一维
img[:, :, 1] = np.ones([400, 400])*255 #第二维全是255
img[:, :, 2] = np.ones([400, 400])*255
cv2.imshow('zizhipictuer', img)
creat_image()
cv2.waitKey(0)
cv2.destroyAllWindows()
运行结果是输出一张白色的图片,也可以单独使用ones函数,代码如下;
# -*- coding=GBK -*-
import cv2 as cv
import numpy as np
def create_image():
img = np.ones([400, 400, 3], np.uint8)
img[:, :, 0] = img[:, :, 0]*255
img[:, :, 1] = img[:, :, 1]*255
img[:, :, 2] = img[:, :, 2]*255
cv.imshow("自制图片", img)
create_image()
cv.waitKey(0)
cv.destroyAllWindows()
# coding = utf-8
import cv2
import numpy as np
def creat_image():
img = np.ones([400, 400, 1], np.uint8)
img = img*127
cv2.imshow("dipicture", img)
creat_image()
cv2.waitKey(0)
cv2.destroyAllWindows()
# coding = utf-8
import cv2
import numpy as np
def inverse(image):
dst = cv2.bitwise_not(image)
cv2.imshow("qufan", dst)
src = cv2.imread('shili.jpg', 1)
cv2.namedWindow("yuanlai", cv2.WINDOW_NORMAL)
cv2.imshow('yuanlai', src)
t1 = cv2.getTickCount()
inverse(src)
t2 = cv2.getTickCount()
time = (t2-t1)*1000/cv2.getTickFrequency()
print("time: %s" % time)
cv2.waitKey(0)
调用库函数bitwise_not 速度非常快
# coding = utf-8
import cv2
#色彩空间的转换
def color_space_demo(image):
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
cv2.imshow("gray", gray)
hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
cv2.imshow('hsv', hsv)
yuv = cv2.cvtColor(image, cv2.COLOR_BGR2YUV)
cv2.imshow("yuv", yuv)
src = cv2.imread('shili.jpg')
cv2.namedWindow('yuanlai', cv2.WINDOW_NORMAL)
cv2.imshow('yuanllai', src)
color_space_demo(src)
cv2.waitKey(0)
cv2.destroyAllWindows()
运行结果如下
HSV色彩空间说明
H:0-180
S:0-255
V:0-255
# -*- coding=GBK -*-
import cv2 as cv
import numpy as np
def nextrace_object_demo():
capture = cv.VideoCapture("G:/1.mp4")#导入视频
while True:
ret, frame = capture.read()
if ret == False:
break
hsv = cv.cvtColor(frame, cv.COLOR_BGR2HSV)#转换色彩空间为hsv
#设置白色的范围,跟踪视频中的白色
lower_hsv = np.array([0, 0, 221])#设置过滤的颜色的低值
upper_hsv = np.array([180, 30, 255])#设置过滤的颜色的高值
mask = cv.inRange(hsv, lower_hsv, upper_hsv)#调节图像颜色信息(H)、饱和度(S)、亮度(V)区间,选择白色区域
cv.imshow("video", frame)
cv.imshow("mask", mask)
if cv.waitKey(50) & 0xFF == ord('q'):
break
nextrace_object_demo()
cv.waitKey(0)
cv.destroyAllWindows()
可以通过下表对应的颜色的数值过滤其他颜色
HSV对应RGB的分量范围;
涉及函数:
split()将彩色图像分割成3个通道
merge()通道合并
#coding = utf-8
import cv2
import numpy as np
src = cv2.imread('shili.jpg')
cv2.namedWindow('yuanlai', cv2.WINDOW_NORMAL)
cv2.imshow('yuanlai',src)
#通道分离,输出三个单通道图片
b, g, r = cv2.split(src) #将彩色图像分割成3个通道
cv2.imshow('blue', b)
cv2.imshow('green', g)
cv2.imshow('red', r)
#通道合并
src = cv2.merge([b, g, r])
cv2.imshow('hebing', src)
#修改某个通道的值
src[:, :, 2] = 100
cv2.imshow('dantngdao', src)
cv2.waitKey(0)
cv2.destroyAllWindows()
相加: add()
相减: subtract()
相乘: divide()
相除: multiply()
原理就是通过获取两张(一次只能获取两张图片)图片的同一位置的色素值来实现运算。
运算要求:两张图片的shape要求一致
# coding = utf-8
import cv2
import numpy as np
#数值的运算
def shu_image(src11, src22):
src = cv2.add(src11, src22)
cv2.imshow('add', src)
src = cv2.subtract(src11, src22)
cv2.imshow('sub', src)
src = cv2.divide(src11, src22)
cv2.imshow('div', src)
src = cv2.multiply(src11, src22)
cv2.imshow('mul',src)
src1 = cv2.imread('1.jpg')
src2 = cv2.imread('2.jpg')
cv2.imshow('yuanlai1', src1)
cv2.imshow('yuanlai2', src2)
shu_image(src1, src2)
cv2.waitKey(0)
cv2.destroyAllWindows()
opencv自带图片色素的处理函数
与: bitwise_add()
或: bitwise_or()
非: bitwise_not()
异或: bitwise_xor()
代码如下:
# coding = utf-8
import cv2
def luo_image(src11, src22):
src = cv2.bitwise_not(src11) # 对一张图片取反操作
cv2.imshow('not', src)
src = cv2.bitwise_and(src11, src22) #两张图片同一位置的像素都不为0时才有输出
cv2.imshow('and', src)
src = cv2.bitwise_or(src11, src22) # 两张图片同一位置的像素不同时为0时有输出
cv2.imshow('or', src)
src = cv2.bitwise_xor(src11, src22) # 两张图片同一位置的像素一个为0,另一个不为0时才有输出
cv2.imshow('xor', src)
src1 = cv2.imread('1.jpg')
src2 = cv2.imread('2.jpg')
cv2.imshow('yuanlai1', src1)
cv2.imshow('yuanlai2', src2)
luo_image(src1, src2)
cv2.waitKey(0)
cv2.destroyAllWindows()
基本原理:两张图片合成
先按照原来的图片的格式新建一个色素全为零的图片,然后按照两张图的比例不同合成一张新图片,用到的有addWeighted函数,代码如下:
# coding = utf-8
import cv2
import numpy as np
#粗略的调节对比度和亮度
def contrast_brightness_image(src1, a, g):
h, w, ch = src1.shape # 获取shape的数值
#新建全零的图片数组,h,w,ch和原来图片一样(色素全为0,输出为0)
src2 = np.zeros([h, w, ch], src1.dtype)
dst = cv2.addWeighted(src1, a, src2, 1-a, g)
cv2.imshow('con_demo', dst)
src = cv2.imread('shili.jpg')
cv2.imshow('yuanlai', src)
contrast_brightness_image(src, 1.2, 10) # 第一个1.2为对比度, 第二个为亮度,数值越大越亮
cv2.waitKey(0)
cv2.destroyAllWindows()
addWeighted函数:官方:计算两个图像阵列的加权和 我的理解是按照所占比例合成两张图片。
addWeighted(InputArray src1, double alpha, InputArray src2, double beta, double gamma, OutputArray dst, int dtype=-1);
一共有七个参数:前4个是两张要合成的图片及它们所占比例,第5个double gamma起微调作用,第6个OutputArray dst是合成后的图片,第七个输出的图片的类型(可选参数,默认-1)
有公式得出两个图片加成输出的图片为:dst=src1alpha+src2beta+gamma
图片的切割与合并
原理通过操作图像矩阵来获取或合并指定图像的位置
代码如下:
# coding = utf-8
import cv2
import numpy as np
#截取图片中的指定区域或在指定区域添加某一张图片
def cut_image(src1):
src2 = src1[5:89, 300:430] #截取第5行到89行和500列到630列
cv2.imshow('cut', src2)
src1[105:189, 200:330] = src2 #指定位置填充,要大小一致才能填充
cv2.imshow('tianchong', src1)
src = cv2.imread('shili.jpg')
cv2.imshow('yuanlai', src)
cut_image(src)
指定颜色填充,代码如下
# coding = utf-8
import cv2
import numpy as np
#指定颜色替换
def fill_image(image):
copyImage = image.copy() #复制原图像
h, w = image.shape[:2]
mask = np.zeros([h+2, w+2], np.uint8) #新建图像矩阵,+2是官方函数要求
cv2.floodFill(copyImage, mask, (0, 80), (0, 100, 255), (100, 100, 50), (50, 50, 50), cv2.FLOODFILL_FIXED_RANGE)
cv2.imshow('tianchong', copyImage)
src = cv2.imread('shili.jpg')
cv2.imshow('yuanlai', src)
fill_image(src)
cv2.waitKey(0)
cv2.destroyAllWindows()
floodFill函数:漫水填充算法:我觉得叫颜色替换好一些
官方定义为:floodFill(InputOutputArray image, Point seedPoint, Scalar newVal, Rect* rect=0, Scalar loDiff=Scalar(), Scalar upDiff=Scalar(), int flags=4 )
不知道为啥,python中调用这个函数,Rect* rect=0这个参数没有,剩下7个参数
通俗解释:floodFill( 1.操作的图像, 2.掩模, 3.起始像素值,4.填充的颜色, 5.填充颜色的低值, 6.填充颜色的高值 ,7.填充的方法)
视频讲解如下:
参数5.填充颜色的低值就是:参数3 处像数值减去 参数5
参数6.填充颜色的高值就是:参数3处的像素值 加上 参数6
即是这两个数值之间的色素替换为参数4的颜色
7.填充的方法
彩色图像一般是FLOODFILL_FIXED_RANGE 指定颜色填充
还有一种是FLOODFILL_MASK_ONLY,mask的指定的位置为零时才填充,不为零不填充
函数的另一种理解:漫水填充说明
看了许多资料,在图像上个人觉得卷积就是:对于某一位置的像素,通过算法来把它附近的所有像素点的值联合起来,重新设置这个像素的大小。(大概就是这样)
这个算法类似有:均值,中值,就是取周围所有像素的均值、中值来设置这个像素的大小。
(关于边界问题:有几种填充方法:补零、边界复制、块复制、镜像复制等方法)
代码如下:
# -*- coding=GBK -*-
# -*- coding=utf-8 -*-
import cv2 as cv
def mo_image(src1):
src2 = cv.blur(src1, (5, 5))
cv.imshow("junzhi", src2)
src2 = cv.medianBlur(src1, 5)
cv.imshow("zhongzhi", src2)
src2 = cv.GaussianBlur(src1, (5, 5), 2)
cv.imshow("gaosi", src2)
src2 = cv.bilateralFilter(src1, 5, 5, 2)
cv.imshow("shuangbianlvbo", src2)
src = cv.imread("shili.jpg")
cv.namedWindow("yuanlai", cv.WINDOW_NORMAL)
cv.imshow("yuanlai", src)
mo_image(src)
cv.waitKey(0)
cv.destroyAllWindows()
1.均值模糊函数blur():定义:blur(src,ksize,dst=None, anchor=None, borderType=None)
定义是有5个参数,但最后三个均为none,所以也就2个参数
src:要处理的原图像
ksize: 周围关联的像素的范围:代码中(5,5)就是5*5的大小,就是计算这些范围内的均值来确定中心位置的大小
2.中值模糊函数medianBlur(): 定义:medianBlur(src, ksize, dst=None)
ksize与blur()函数不同,不是矩阵,而是一个数字,例如为5,就表示了5*5的方阵
3.高斯平滑函数GaussianBlur():定义:GaussianBlur(src, ksize, sigmaX, dst=None, sigmaY=None, borderType=None)
sigmaX:标准差
4.双边滤波函数bilateralFilter():定义:bilateralFilter(src, d, sigmaColor, sigmaSpace, dst=None, borderType=None)
d:邻域直径
sigmaColor:颜色标准差
sigmaSpace:空间标准差
# -*- coding=GBK -*-
import cv2 as cv
from matplotlib import pyplot as plt
# 画出图像的直方图
def hist_image(image):
color = ("blue", "green", "red")
for i, color in enumerate(color):
hist = cv.calcHist([image], [i], None, [256], [0, 256])
plt.plot(hist, color=color)
plt.xlim([0, 256])
plt.show()
src = cv.imread("shili.jpg")
cv.namedWindow("原来", cv.WINDOW_NORMAL)
cv.imshow("yuanlai", src)
hist_image(src)
cv.waitKey(0)
cv.destroyAllWindows()
输出结果
1.numpy的ravel函数功能是将多维数组降为一维数组。参考博客:https://blog.csdn.net/lanchunhui/article/details/50354978
2.matplotlib.pyplot.hist函数主要是计算直方图。
hist函数原型:hist(x, bins=None, range=None, density=None, weights=None, cumulative=False, bottom=None, histtype=‘bar’, align=‘mid’, orientation=‘vertical’, rwidth=None, log=False, color=None, label=None, stacked=False, normed=None, hold=None, data=None, **kwargs)
x参数表示是一个数组或一个序列,是指定每个bin(箱子)分布的数据
bins参数表示指定bin(箱子)的个数,也就是总共有几条条状图
range参数表示箱子的下限和上限。即横坐标显示的范围,范围之外的将被舍弃。
参考博客:https://blog.csdn.net/u013571243/article/details/48998619
3.enumerate() 函数用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列,同时列出数据下标和数据,一般用在 for 循环当中。
4.cv2.calcHist的原型为:calcHist(images, channels, mask, histSize, ranges[, hist[, accumulate]]) -> hist
images参数表示输入图像,传入时应该用中括号[ ]括起来
channels参数表示传入图像的通道,如果是灰度图像,那就不用说了,只有一个通道,值为0,如果是彩色图像(有3个通道),那么值为0,1,2,中选择一个,对应着BGR各个通道。这个值也得用[ ]传入。
mask参数表示掩膜图像。如果统计整幅图,那么为None。主要是如果要统计部分图的直方图,就得构造相应的掩膜来计算。
histSize参数表示灰度级的个数,需要中括号,比如[256]
ranges参数表示像素值的范围,通常[0,256]。此外,假如channels为[0,1],ranges为[0,256,0,180],则代表0通道范围是0-256,1通道范围0-180。
hist参数表示计算出来的直方图。
参考:https://blog.csdn.net/YZXnuaa/article/details/79231817
5.关于pyplot模块里plot()函数、xlim()函数等的用法参考:
https://blog.csdn.net/cymy001/article/details/78344316
https://blog.csdn.net/chinwuforwork/article/details/51786967
直方图均衡化:提升对比度的两种方法:默认、自定义
# -*- coding=GBK -*-
import cv2 as cv
from matplotlib import pyplot as plt
#提升对比度(默认提升),只能是灰度图像
def equalHist_image(image):
gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
cv.imshow("原来", gray)#因为只能处理灰度图像,所以输出原图的灰度图像用于对比
dst = cv.equalizeHist(gray)
cv.imshow("默认处理", dst)
#对比度限制(自定义提示参数)
def clahe_image(image):
gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
clahe = cv.createCLAHE(clipLimit=2.0, tileGridSize=(4, 4))#clipLimit是对比度的大小,tileGridSize是每次处理块的大小
dst = clahe.apply(gray)
cv.imshow("自定义处理", dst)
src = cv.imread("C://1.jpg")
equalHist_image(src)
clahe_image(src)
cv.waitKey(0)
cv.destroyAllWindows()
模板匹配:通俗讲就是以图找图,通过图中的一部分来找它在图中的位置
通过三种方式来匹配:cv.TM_SQDIFF_NORMED, cv.TM_CCORR_NORMED, cv.TM_CCOEFF_NORMED
代码如下:
# -*- coding=GBK -*-
import cv2 as cv
import numpy as np
#模版匹配
def template_image():
tpl = cv.imread("C://2.jpg")
target = cv.imread("C://1.jpg")
cv.imshow("模板", tpl)
cv.imshow("原图", target)
methods = [cv.TM_SQDIFF_NORMED, cv.TM_CCORR_NORMED, cv.TM_CCOEFF_NORMED]
th, tw = tpl.shape[:2]
for md in methods:
print(md)
result = cv.matchTemplate(target, tpl, md)
min_val, max_val, min_loc, max_loc = cv.minMaxLoc(result)
if md == cv.TM_SQDIFF_NORMED:
tl = min_loc
else:
tl = max_loc
br = (tl[0]+tw, tl[1]+th)
cv.rectangle(target, tl, br, (0, 0, 255), 2)
cv.imshow("匹配"+np.str(md), target)
template_image()
cv.waitKey(0)
cv.destroyAllWindows()
# -*- coding=GBK -*-
import cv2 as cv
import numpy as np
#图像二值化 0白色 1黑色
#全局阈值
def threshold_image(image):
gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
cv.imshow("原来", gray)
ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)#大律法,全局自适应阈值 参数0可改为任意数字但不起作用
print("阈值:%s" % ret)
cv.imshow("OTSU", binary)
ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY | cv.THRESH_TRIANGLE)#TRIANGLE法,,全局自适应阈值, 参数0可改为任意数字但不起作用,适用于单个波峰
print("阈值:%s" % ret)
cv.imshow("TRIANGLE", binary)
ret, binary = cv.threshold(gray, 150, 255, cv.THRESH_BINARY)# 自定义阈值为150,大于150的是白色 小于的是黑色
print("阈值:%s" % ret)
cv.imshow("自定义", binary)
ret, binary = cv.threshold(gray, 150, 255, cv.THRESH_BINARY_INV)# 自定义阈值为150,大于150的是黑色 小于的是白色
print("阈值:%s" % ret)
cv.imshow("自定义反色", binary)
ret, binary = cv.threshold(gray, 150, 255, cv.THRESH_TRUNC)# 截断 大于150的是改为150 小于150的保留
print("阈值:%s" % ret)
cv.imshow("截断1", binary)
ret, binary = cv.threshold(gray, 150, 255, cv.THRESH_TOZERO)# 截断 小于150的是改为150 大于150的保留
print("阈值:%s" % ret)
cv.imshow("截断2", binary)
src = cv.imread("C://1.jpg")
threshold_image(src)
cv.waitKey(0)
cv.destroyAllWindows()
函数threshold()的参数说明:
cv.THRESH_BINARY | cv.THRESH_OTSU)#大律法,全局自适应阈值 参数0可改为任意数字但不起作用
cv.THRESH_BINARY | cv.THRESH_TRIANGLE)#TRIANGLE法,,全局自适应阈值, 参数0可改为任意数字但不起作用,适用于单个波峰
cv.THRESH_BINARY)# 自定义阈值为150,大于150的是白色 小于的是黑色
cv.THRESH_BINARY_INV)# 自定义阈值为150,大于150的是黑色 小于的是白色
cv.THRESH_TRUNC)# 截断 大于150的是改为150 小于150的保留
cv.THRESH_TOZERO)# 截断 小于150的是改为150 大于150的保留
# -*- coding=GBK -*-
import cv2 as cv
import numpy as np
#求出图像均值作为阈值来二值化
def custom_image(image):
gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
cv.imshow("原来", gray)
h, w = gray.shape[:2]
m = np.reshape(gray, [1, w*h])#化为一维数组
mean = m.sum() / (w*h)
print("mean: ", mean)
ret, binary = cv.threshold(gray, mean, 255, cv.THRESH_BINARY)
cv.imshow("二值", binary)
src = cv.imread("C://1.jpg")
custom_image(src)
cv.waitKey(0)
cv.destroyAllWindows()
# -*- coding=GBK -*-
import cv2 as cv
import numpy as np
#求出图像均值作为阈值来二值化
def custom_image(image):
gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
cv.imshow("原来", gray)
h, w = gray.shape[:2]
m = np.reshape(gray, [1, w*h])#化为一维数组
mean = m.sum() / (w*h)
print("mean: ", mean)
ret, binary = cv.threshold(gray, mean, 255, cv.THRESH_BINARY)
cv.imshow("二值", binary)
src = cv.imread("C://1.jpg")
custom_image(src)
cv.waitKey(0)
cv.destroyAllWindows()
要求:拉普拉斯金字塔时,图像大小必须是2的n次方*2的n次方,不然会报错
# -*- coding=GBK -*-
import cv2 as cv
#高斯金字塔
def pyramid_image(image):
level = 3#金字塔的层数
temp = image.copy()#拷贝图像
pyramid_images = []
for i in range(level):
dst = cv.pyrDown(temp)
pyramid_images.append(dst)
cv.imshow("高斯金字塔"+str(i), dst)
temp = dst.copy()
return pyramid_images
#拉普拉斯金字塔
def laplian_image(image):
pyramid_images = pyramid_image(image)
level = len(pyramid_images)
for i in range(level-1, -1, -1):
if(i-1) < 0 :
expand = cv.pyrUp(pyramid_images[i], dstsize=image.shape[:2])
lpls = cv.subtract(image, expand)
cv.imshow("拉普拉斯"+str(i), lpls)
else:
expand = cv.pyrUp(pyramid_images[i], dstsize=pyramid_images[i-1].shape[:2])
lpls = cv.subtract(pyramid_images[i-1], expand)
cv.imshow("拉普拉斯"+str(i), lpls)
src = cv.imread("C://01.jpg")
cv.imshow("原来", src)
laplian_image(src)
cv.waitKey(0)
cv.destroyAllWindows()
# -*- coding=GBK -*-
import cv2 as cv
#图像梯度:索贝尔算子
def sobel_image(image):
grad_x = cv.Sobel(image, cv.CV_32F, 1, 0)#x方向导数
grad_y = cv.Sobel(image, cv.CV_32F, 0, 1)#y方向导数
gradx = cv.convertScaleAbs(grad_x)
grady = cv.convertScaleAbs(grad_y)
cv.imshow("X方向", gradx)#颜色变化在水平分层
cv.imshow("Y方向", grady)#颜色变化在垂直分层
gradxy = cv.addWeighted(gradx, 0.5, grady, 0.5, 0)
cv.imshow("合成", gradxy)
src = cv.imread("C://1.jpg")
cv.imshow("原来", src)
sobel_image(src)
cv.waitKey(0)
cv.destroyAllWindows()
#图像梯度:scharr算子:增强边缘
def scharr_image(image):
grad_x = cv.Scharr(image, cv.CV_32F, 1, 0)#x方向导数
grad_y = cv.Scharr(image, cv.CV_32F, 0, 1)#y方向导数
gradx = cv.convertScaleAbs(grad_x)
grady = cv.convertScaleAbs(grad_y)
cv.imshow("X方向", gradx)#颜色变化在水平分层
cv.imshow("Y方向", grady)#颜色变化在垂直分层
gradxy = cv.addWeighted(gradx, 0.5, grady, 0.5, 0)
cv.imshow("合成", gradxy)
#拉普拉斯算子
def lapalian_image(image):
dst = cv.Laplacian(image, cv.CV_32F)
lpls = cv.convertScaleAbs(dst)
cv.imshow("拉普拉斯", lpls)
# -*- coding=GBK -*-
import cv2 as cv
#边缘检测述算法
def edge_image(image):
blurred = cv.GaussianBlur(image, (3, 3), 0)
gray = cv.cvtColor(blurred, cv.COLOR_BGR2GRAY)
xgrad = cv.Sobel(gray, cv.CV_16SC1, 1, 0)
ygrad = cv.Sobel(gray, cv.CV_16SC1, 0, 1)
edge_output = cv.Canny(xgrad, ygrad, 50, 150)
cv.imshow("canny边缘", edge_output)
dst = cv.bitwise_and(image, image, mask=edge_output)
cv.imshow("color边缘", dst)
src = cv.imread("C://1.jpg")
cv.imshow("原来", src)
edge_image(src)
cv.waitKey(0)
cv.destroyAllWindows()
# -*- coding=GBK -*-
import cv2 as cv
import numpy as np
#霍夫直线检测
def line_image(image):
gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
edges = cv.Canny(gray, 50, 150, apertureSize=3)
lines = cv.HoughLines(edges, 1, np.pi/180, 200)
for line in lines:
rho, theta = line[0]
a = np.cos(theta)
b = np.sin(theta)
x0 = a * rho
y0 = b * rho
x1 = int(x0+1000*(-b))
y1 = int(y0+1000*(a))
x2 = int(x0-1000*(-b))
y2 = int(y0-1000*(a))
cv.line(image, (x1, y1), (x2, y2), (0, 0, 255), 2)
cv.imshow("直线", image)
src = cv.imread("C://01.png")
cv.imshow("原来", src)
line_image(src)
cv.waitKey(0)
cv.destroyAllWindows()
import cv2 as cv
import numpy as np
#圆检测
def circles_image(image):
dst = cv.pyrMeanShiftFiltering(image, 10, 100)
cimage = cv.cvtColor(dst, cv.COLOR_BGR2GRAY)
circles = cv.HoughCircles(cimage, cv.HOUGH_GRADIENT, 1, 20, param1=50, param2=30, minRadius=0, maxRadius=0)
circles = np.uint16(np.around(circles))
for i in circles[0, :]:
cv.circle(image, (i[0], i[1]), i[2], (0, 0, 255), 2)
cv.circle(image, (i[0], i[1]), 2, (255, 0, 255), 2)
cv.imshow(“圆形”, image)
src = cv.imread(“C://04.jpg”)
cv.imshow(“原来”, src)
circles_image(src)
cv.waitKey(0)
cv.destroyAllWindows()
# -*- coding=GBK -*-
import cv2 as cv
import numpy as np
#轮廓发现
def contous_image(image):
dst = cv.GaussianBlur(image, (3, 3), 0)
gray = cv.cvtColor(dst, cv.COLOR_BGR2GRAY)
ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)
cv.imshow("二值化", binary)
cloneImage, contous, heriachy = cv.findContours(binary, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
for i,contou in enumerate(contous):
cv.drawContours(image, contous, i, (0, 0, 255), 1)
cv.imshow("轮廓", image)
for i,contou in enumerate(contous):
cv.drawContours(image, contous, i, (0, 0, 255), -1)
cv.imshow("轮廓覆盖", image)
src = cv.imread("D://1.jpg")
cv.imshow("原来", src)
contous_image(src)
cv.waitKey(0)
cv.destroyAllWindows()
作用:删除图像的小的干扰项
# -*- coding=GBK -*-
import cv2 as cv
#图像的开闭操作
def open_image(image):
gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)
cv.imshow("二值化", binary)
kernel = cv.getStructuringElement(cv.MORPH_RECT, (5, 5))
binary = cv.morphologyEx(binary, cv.MORPH_OPEN, kernel)
cv.imshow("开操作", binary)
def close_image(image):
gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)
kernel = cv.getStructuringElement(cv.MORPH_RECT, (5, 5))
binary = cv.morphologyEx(binary, cv.MORPH_CLOSE, kernel)
cv.imshow("闭操作", binary)
src = cv.imread("C://1.jpg")
cv.imshow("原来", src)
open_image(src)
close_image(src)
cv.waitKey(0)
cv.destroyAllWindows()
分水岭分割流程:图像->灰度->二值->距离变换->寻找种子->生成Marker->分水岭变换->输出
# -*- coding=GBK -*-
import cv2 as cv
import numpy as np
# 分水岭算法
def water_image():
print(src.shape)
blurred = cv.pyrMeanShiftFiltering(src, 10, 100) # 去除噪点
# gray\binary image
gray = cv.cvtColor(blurred, cv.COLOR_BGR2GRAY)
ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)
cv.imshow("二值图像", binary)
# morphology operation
kernel = cv.getStructuringElement(cv.MORPH_RECT, (3, 3))
mb = cv.morphologyEx(binary, cv.MORPH_OPEN, kernel, iterations=2)
sure_bg = cv.dilate(mb, kernel, iterations=3)
cv.imshow("形态操作", sure_bg)
# distance transform
dist = cv.distanceTransform(mb, cv.DIST_L2, 3)
dist_output = cv.normalize(dist, 0, 1.0, cv.NORM_MINMAX)
cv.imshow("距离变换", dist_output*70)
ret, surface = cv.threshold(dist, dist.max()*0.6, 255, cv.THRESH_BINARY)
cv.imshow("寻找种子", surface)
surface_fg = np.uint8(surface)
unknown = cv.subtract(sure_bg, surface_fg)
ret, markers = cv.connectedComponents(surface_fg)
print(ret)
# watershed transfrom
markers += 1
markers[unknown == 255] = 0
markers = cv.watershed(src, markers=markers)
src[markers == -1] = [0, 0, 255]
cv.imshow("分水岭结果", src)
src = cv.imread("C://02.png")
cv.imshow("原来", src)
water_image()
cv.waitKey(0)
cv.destroyAllWindows()
这里需要使用haarcascade_frontalface_alt_tree.xml,可以自行百度
# -*- coding=GBK -*-
import cv2 as cv
# 人脸检测
def face_image():
gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY)
face_detector = cv.CascadeClassifier("haarcascade_frontalface_alt_tree.xml")
faces = face_detector.detectMultiScale(gray, 1.02, 5) # 第二个参数是移动距离,第三个参数是识别度,越大识别读越高
for x, y, w, h in faces:
cv.rectangle(src, (x, y), (x+w, y+h), (0, 0, 255), 2) # 后两个参数,一个是颜色,一个是边框宽度
cv.imshow("结果", src)
src = cv.imread("C://4.jpg")
cv.imshow("原来", src)
face_image()
cv.waitKey(0)
cv.destroyAllWindows()
# -*- coding=GBK -*-
import cv2 as cv
# 摄像头人脸检测
def face_image(src):
gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY)
face_detector = cv.CascadeClassifier("haarcascade_frontalface_alt_tree.xml")
faces = face_detector.detectMultiScale(gray, 1.02, 5) # 第二个参数是移动距离,第三个参数是识别度,越大识别读越高
for x, y, w, h in faces:
cv.rectangle(src, (x, y), (x+w, y+h), (0, 0, 255), 2) # 后两个参数,一个是颜色,一个是边框宽度
cv.imshow("结果", src)
capture = cv.VideoCapture(0)
while(True):
ret, frame = capture.read()
frame = cv.flip(frame, 1)
face_image(frame)
if cv.waitKey(10) & 0xFF == ord('q'): # 键盘输入q退出窗口,不按q点击关闭会一直关不掉 也可以设置成其他键。
break
face_image()
cv.waitKey(0)
cv.destroyAllWindows()
视频中人脸检测还可以
验证码识别前期准备:
1.安装:tesseract-oc,直接安装就行,要配环境,下载地址点这里
参考资料:点这里,再说一下,实测一定要配环境!!!
2.安装pytesseract:pip install pytesseract
# -*- coding=GBK -*-
import cv2 as cv
import Image
import pytesseract
def recognize_text():
gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY)
ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY_INV | cv.THRESH_OTSU)
kernel = cv.getStructuringElement(cv.MORPH_RECT, (1, 6))
binl = cv.morphologyEx(binary, cv.MORPH_OPEN, kernel)
kernel = cv.getStructuringElement(cv.MORPH_RECT, (5, 1))
open_out = cv.morphologyEx(binl, cv.MORPH_OPEN, kernel)
cv.bitwise_not(open_out, open_out) # 背景变为白色
cv.imshow("转换", open_out)
textImage = Image.fromarray(open_out)
text = pytesseract.image_to_string(textImage)
print("This OK:%s"%text)
src = cv.imread("C://yzm.jpg")
cv.imshow("原来", src)
recognize_text()
cv.waitKey(0)
cv.destroyAllWindows()