1.基本语法
src = cv.imread("E:\\1.jpg") //获取图片位置
cv.namedWindow("Image",cv.WINDOW_AUTOSIZE) //命名显示窗口并设置属性
cv.imshow("Image",img) //显示窗口并将图片显示
cv.waitKey(0) //等待输入响应
cv.destroyAllWindows() //销毁窗口
2.图像加载与保存
图片属性
1.通道数目
2.高宽
3.像素数据
4.图像类型
图片属性获取
print(type(image)) //显示image类型
print(image.shape) //显示图片宽高和通道数
print(image.size) //显示总像素数据大小
print(image.dtype) //通道所占位数
摄像头获取
capture=cv.VideoCapture(0) //获取视频
while(True):
ret, frame=capture.read() //调用摄像头
frame=cv.flip(frame,1) //镜像调整
cv.imshow("video",frame) //显示窗口
c=cv.waitKey(50)
if c==27:
break
保存图片
cv.imwrite("E:/result.png",img) //将img保存在路径下并命名与格式
3.Numpy数组操作
包介绍详细 www.numpy.org
作用:
遍历数组中的每个像素点
修改数组中像素点的值
data\dtype\size\shape\len
遍历图像像素
def access_pixels(image):
print(image.shape)
height=image.shape[0]
width=image.shape[1]
channel=image.shape[2]
print("width:%s,height:%s,channels:%s"%(width,height,channel))
for rowin range(height):
for colin range(width):
for cin range(channel):
pv = image[row, col, c]
image[row,col,c]=255-pv
cv.imshow("pixels_demo",image)
注:对于上述操作可以用像素取反函数完成
def inverse(image):
dst=cv.bitwise_not(image) //像素取反
cv.imshow("show",dst)
初始化图片
np.zeros([400,400,3],np.uint8) //初始化0
np.ones([400,400])*255 //初始化1
fill(122) //填充数组
reshape([1,9]) //改变数组形状
4.色彩空间
相关概念
RGB,HSV, HIS,YCrCb, YUV
代码检测:
gray=cv.cvtColor(image,cv.COLOR_BGR2GRAY)
cv.imshow("gray",gray)
hsv=cv.cvtColor(image,cv.COLOR_BGR2HSV)
cv.imshow("hsv",hsv)
yuv = cv.cvtColor(image, cv.COLOR_BGR2YUV)
cv.imshow("yuv", yuv)
Ycrcb = cv.cvtColor(image, cv.COLOR_BGR2YCrCb)
cv.imshow("Ycrcb", Ycrcb)
色彩空间转换API
用inRange处理
获取视频中的蓝色:
capture = cv.VideoCapture("E:\\test.mp4")
while(True):
ret, frame = capture.read()
if ret ==False:
break
hsv=cv.cvtColor(frame, cv.COLOR_BGR2HSV)
lower=np.array([100,43,46])
upper=np.array([124,255,255])#蓝色区域范围
mask=cv.inRange(hsv,lowerb=lower,upperb=upper)
cv.imshow("mask",mask)
cv.imshow("video", frame)
c = cv.waitKey(40)
if c ==27:
break
分离与合并通道
r,g,b= cv.split(src) #分离
cv.imshow("blue",b)
cv.imshow("green",g)
cv.imshow("red",r)
cv.merge([r,g,b]) #合并
5.像素运算
算术运算
加减乘除——调节亮度,对比度
def add_demo(m1,m2):
dst = cv.add(m1, m2) #加
cv.imshow("add", dst)
def subtract_demo(m1,m2):
dst = cv.subtract(m1, m2) #减
cv.imshow("substract", dst)
def divide_demo(m1,m2):
dst = cv.divide(m1, m2) #除
cv.imshow("divide", dst)
def multiply_demo(m1,m2):
dst = cv.multiply(m1, m2) #乘
cv.imshow("multiply", dst)
注:mean(src) #求均值
M,dev = meanStdDev(src) #返回均值和方差(对比度)
逻辑运算
与或非——遮罩层控制
dst = cv.bitwise_and(m1, m2) #与
dst = cv.bitwise_or(m1, m2) #或
dst = cv.bitwise_not(m1) #非
调整亮度对比度
#调整对比度与亮度 c:对比度,b:亮度
def contract_brightness_demo(image,c,b):
h,w,ch=image.shape
blank=np.zeros([h,w,ch],image.dtype) #调整亮度对比度
dst=cv.addWeighted(image,c,blank,1-c,b)
cv.imshow("con_bri_demo", dst)
6.ROI与泛洪填充
注:ROI:所选处理区域
#改变图片某区域颜色
face= src[50:250,100:300]
gray=cv.cvtColor(face,cv.COLOR_BGR2GRAY)
backface=cv.cvtColor(gray,cv.COLOR_GRAY2BGR)
face= src[50:250,100:300]=backface
cv.imshow("face",src)
泛洪填充
def fill_color_demo(image):
copyImg=image.copy()
h,w=image.shape[:2]
mask= np.zeros([h+2,w+2],np.uint8)
cv.floodFill(copyImg,mask,(30,30),(0,255,255),(100,100,100),(50,50,50), cv.FLOODFILL_FIXED_RANGE) #改变图像 泛洪填充
cv.imshow("fill_color",copyImg)
def fill_binary():
image=np.zeros([400,400,3],np.uint8)
image[100:300 , 100:300 , :] =255
cv.imshow("fill_binary",image)
mask=np.ones([402,402,1],np.uint8)
mask[101:301,101:301] =0
cv.floodFill(image,mask,(200,200),(0,0,255),cv.FLOODFILL_MASK_ONLY)
#不改变图像 只填充遮罩层
cv.imshow("filled binary",image)
floodFill()
floodFill(Mat image,Mat mask,Point seedPoint,Scalar newVal)
floodFill(image, mask, seedpoint ,newVal,rect,loDiff,upDiff,flags)
src(seed.x,seed.y)-loDiff<=src(x,y)<=src(seed.x,seed.y)+upDiff合并图像
作用:合并图像
7.模糊操作
均值模糊,中值模糊,自定义模糊
模糊是卷积的一种表象
dst=cv.blur(image,(15,1)) #x方向15像素卷积,y方向1像素卷积,不模糊
dst=cv.medianBlur(image,5) #中值模糊 常用于去燥点
kernel=np.ones([5,5],np.float32)/25
dst=cv.filter2D(image,-1,kernel=kernel) #自定义模糊
高斯模糊
def clamp(pv):
if pv>255:
return 255
if pv<0:
return 0
else:
return pv
高斯模糊原理代码
def gaosi_noise(image):
h,w,c = image.shape
for rowin range(h):
for colin range(w):
s=np.random.normal(0,20,3)
b=image[row,col,0]#blue
g=image[row,col,1]#green
r=image[row,col,2]#red
image[row,col,0] = clamp(b+s[0])
image[row,col,1] = clamp(g+s[1])
image[row,col,2] = clamp(r+s[2])
cv.imshow("noise image",image)
API内置函数
dst=cv.GaussianBlur(src,(0,0),15) #0*0高斯模糊
8.边缘保留滤波(EPF)
高斯双边,均值迁移,操作
双边模糊:
dst=cv.bilateralFilter(image,0,100,15)
均值迁移:
dst=cv.pyrMeanShiftFiltering(image,10,50)
作用:美颜,磨皮美白
9.图像直方图(待学)
10.模块匹配
在整个图像区域发现与给定子图像匹配的小块区域
模板匹配算法
算法种类
算法公式
通过三种算法匹配
def template_demo():
tpl=cv.imread("E:\\3.png") #要匹配的图片
target=cv.imread("E:\\2.png") #总的大图片
cv.imshow("tpl",tpl)
cv.imshow("target",target)
method=[cv.TM_SQDIFF_NORMED,cv.TM_CCORR_NORMED,cv.TM_CCOEFF_NORMED]
th,tw=tpl.shape[:2]
for mdin method:
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("match-"+np.str(md),target)
11.图像二值化
二值图像(Binary Image), 二值化方法
二值化方法:
全局阈值,局部阈值
全局阈值:
OTSU方法阈值
def threshold_demo(image):
gray=cv.cvtColor(image,cv.COLOR_BGR2GRAY)
ret, binary=cv.threshold(gray,0,255,cv.THRESH_BINARY | cv.THRESH_OTSU)
#0,255表示偏向的两极
print("threshold value %s"%ret)
cv.imshow("binary",binary)
cv.THRESH_TRIANGLE方法
局部阈值:
def local_threshold_demo(image):
gray=cv.cvtColor(image,cv.COLOR_BGR2GRAY)
binary=cv.adaptiveThreshold(gray,255,cv.ADAPTIVE_THRESH_MEAN_C,cv.THRESH_BINARY,25,10)
#ADAPTIVE_THRESH_MEAN_C方法
#还有ADAPTIVE_THRESH_GAUSSIAN_C方法
cv.imshow("binary",binary)
自定义:
def custom_threshold_demo(image):
gray=cv.cvtColor(image,cv.COLOR_BGR2GRAY)
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",binary)
超大图片二值化
def image_big_binary(image):
print(image.shape)
cw =256
ch =256
h,w=image.shape[:2]
gray =cv.cvtColor(image,cv.COLOR_BGR2GRAY)
for rowin range(0,h,ch):
for colin range(0,w,cw):
roi = gray[row:row+ch,col:cw+col]
ret,dst = cv.threshold(roi, 0, 255, cv.THRESH_BINARY| cv.THRESH_OTSU)
gray[row:row+ch,col:cw+col] =dst
print(np.std(dst),np.mean(dst))
cv.imshow("gray",gray)
12.图像金字塔
高斯金字塔 与拉普拉斯金字塔,图像金字塔原理
图像金字塔原理 reduce=高斯模糊+降采样
expand=扩大+卷积
PyrDown:降采样
PyrUp:还原
13.图像梯度
一阶导数与Sobel算子,二阶导数和拉普拉斯算子
Sobel算子
def soble_demo(image):
grad_x = cv.Sobel(image,cv.CV_32F,1,0) //Sobel算子提取边缘
grad_y = cv.Scharr(image,cv.CV_32F,0,1) //Scharr是Sobel算子加强版
gradx=cv.convertScaleAbs(grad_x)
grady=cv.convertScaleAbs(grad_y)
cv.imshow("grad_x",gradx)
cv.imshow("grad_y",grady)
gradxy = cv.addWeighted(gradx,0.5,grady,0.5,0)
cv.imshow("grad",gradxy)
拉普拉斯算子
def lapilian_demo(image):
#dst = cv.Laplacian(image,cv.CV_32F) #拉普拉斯算子
#lpls = cv.convertScaleAbs(dst)
kernel= np.array([[1,1,1],[1,-8,1],[1,1,1]])
dst=cv.filter2D(image,cv.CV_32F,kernel=kernel)
lpls=cv.convertScaleAbs(dst)
cv.imshow("lapl",lpls)
边缘提取
canny算法边缘检测算法
高斯模糊,灰度转换,计算梯度,非最大信号抑制,高低阈值链接
def canny_demo(image):
blur=cv.GaussianBlur(image,(3,3),0)
gray=cv.cvtColor(blur,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)
#50为低阈值,150为高阈值,高一版是低的三倍或两倍
cv.imshow("Edge",edge_output)
dst=cv.bitwise_and(image,image,mask=edge_output)
cv.imshow("Color_edge",dst)
14.直线检测
霍夫直线变换检测
def line_detection(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 linein lines:
print(type(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("lines",image)
def line_possible(image):
gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
edges = cv.Canny(gray, 50, 150, apertureSize=3)
lines = cv.HoughLinesP(edges, 1, np.pi /180, 100,minLineLength=50,maxLineGap=10)
for linein lines:
x1,y1,x2,y2=line[0]
cv.line(image, (x1, y1), (x2, y2), (0, 0, 255), 2)
cv.imshow("lines_possible", image)
15.圆检测
霍夫圆检测
首先对图像进行中值滤波
1.检测边缘,发现可能圆心 2.基于第一步开始计算最佳半径大小
def circle_demo(image):
dst=cv.pyrMeanShiftFiltering(image,10,100)
gary=cv.cvtColor(dst,cv.COLOR_BGR2GRAY)
circle=cv.HoughCircles(gary,cv.HOUGH_GRADIENT,1,50,param1=50,param2=30,minRadius=0,maxRadius=0)
#调整50这个参数根据具体情况调整
circle=np.uint16(np.around(circle))
for iin circle[0,:]:
cv.circle(image,(i[0],i[1]),i[2],(0,0,255),2)
cv.circle(image,(i[0],i[1]),2,(0,0,255),2)
cv.imshow("circle",image)
16.轮廓检测
findContours发现轮廓
drawContours绘制轮廓
用梯度避免阈值烦恼
def contours_demo(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",binary)
cloneImg,contours,heriachy=cv.findContours(binary,cv.RETR_TREE,cv.CHAIN_APPROX_SIMPLE)
for i,contourin enumerate(contours):
cv.drawContours(image,contours,i,(0,0,255),2)
#填充轮廓最后的2改成-1
print(i)
cv.imshow("contours",image)
17.对象检测
弧长面积,多边形拟合,几何矩计算
def measure_object(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_INV | cv.THRESH_OTSU)
print("threshold value %s"%ret)
cv.imshow("binary",binary)
dstt = cv.cvtColor(binary, cv.COLOR_GRAY2BGR)
outImg,contours,hireachy=cv.findContours(binary,cv.RETR_TREE,cv.CHAIN_APPROX_SIMPLE)
for i,contourin enumerate(contours):
#cv.drawContours(image, contours, i, (0, 0, 255), 2)
area = cv.contourArea(contour)
print("area",area)
x, y, w, h = cv.boundingRect(contour)
mm = cv.moments(contour)
print(type(mm))
cx = mm['m10']/mm['m00']
cy = mm['m01']/mm['m00']#找到重心
cv.circle(image,(np.int(cx),np.int(cy)),3,(0,255,255),-1)
#cv.rectangle(image, (x, y), (x+w), (x+h), (0, 0, 255), 2)
approxCurve = cv.approxPolyDP(contour, 10, True) #逼近边数
if approxCurve.shape[0] ==3:
cv.drawContours(dstt, contours, i, (0, 255, 0), 2)
if approxCurve.shape[0]==4:
cv.drawContours(dstt, contours, i, (0, 0, 255), 2)
if approxCurve.shape[0] >4:
cv.drawContours(dstt, contours, i, (255, 0, 0), 2)
print(approxCurve.shape)
cv.imshow("measure", dstt)