opencv-python 教程整理

应该记住的是图像的宽对应的是列数,高对应的是行数。

 读取图片

import cv2 as cv
import sys
from matplotlib import pyplot as plt
img=cv.imread('bg.jpg',-1) # -1 是彩色图片
#img=cv.imread('bg.jpg',0) #0 是 灰度图片
#img=cv.imread(cv.samples.findFile("C:/Users/Administrator/Desktop/bg.jpg"))
img=cv.resize(img,(640,480))
if img is None:
    sys.exit("no this img!")
    
#cv.namedWindow('img',cv.WINDOW_NORMAL)
img=cv.cvtColor(img, cv.COLOR_BGR2GRAY)
cv.imshow("img",img)
if cv.waitKey(0)& 0xff==ord('q'):
    cv.destroyAllWindows()

elif cv.waitKey(0)& 0xff==ord('s'):
    cv.imwrite("C:/Users/Administrator/Desktop/save.jpg",img)
    cv.destroyAllWindows()
    

读摄像头

import cv2 as cv
import sys

cap=cv.VideoCapture(0)
cap.set(3,640)
cap.set(4,480)

if not cap.isOpened():
    sys.exit("no camera!")
    

ret,frame=cap.read()
while (ret):
    ret,frame=cap.read()
    gray=frame.copy()
    gray=cv.cvtColor(gray, cv.COLOR_BGR2GRAY)
    if ret:
        
        cv.imshow('img',frame)
        cv.imshow('gray',gray)
         
    if cv.waitKey(1) & 0xff ==ord('q'):
        break
    
    
cap.release()
cv.destroyAllWindows()
        

录摄像头视频

import cv2 as cv
import sys

cap=cv.VideoCapture(0)
fourcc=cv.VideoWriter_fourcc(*'XVID')
out=cv.VideoWriter('out.avi',fourcc,25,(640,480))

while(cap.isOpened()):
    ret,frame=cap.read()
    if ret:
        out.write(frame)
        cv.imshow('img',frame)
    if cv.waitKey(1) &0xff ==ord('q'):
        break
    
cap.release()
cv.destroyAllWindows()        

绘画

import cv2 as cv
import numpy as np

bg=np.zeros((640,480,3),dtype=np.uint8)
font=cv.FONT_HERSHEY_SIMPLEX
cv.rectangle(bg,(0,0),(255,255),(0,0,255),-1,lineType=cv.LINE_AA)
cv.line(bg,(255,255),(480,480),(0,255,255),2,lineType=cv.LINE_AA)
cv.putText(bg,'hello world!',(255,260),font,1,(255,255,255),5)
cv.imshow('line',bg)
cv.waitKey(0)
cv.destroyAllWindows()

几何变换

扩展缩放,只改变图像的尺寸大小

应该记住的是图像的宽对应的是列数,高对应的是行数。

INTER_NEAREST | 最近邻插值
INTER_LINEAR | 双线性插值(默认设置)
INTER_AREA |  使用像素区域关系进行重采样
INTER_CUBIC  | 4x4像素邻域的双三次插值
INTER_LANCZOS4 |  8x8像素邻域的Lanczos

import cv2 
import numpy as np

def cv_show(name,img):
	cv2.imshow(name, img)
	cv2.waitKey(0)
	cv2.destroyAllWindows()

img=cv2.imread('knife.jpg')
rows,cols,_=img.shape
M=np.float32([[1,0,100],[0,1,100]]) #create the move matrix   x move left 100 and y move down 100 pixel

move=cv2.warpAffine(img,M,(cols,rows)) #  the size of output  tip:(cols,rows)
cv_show('move',move)

M=cv2.getRotationMatrix2D((rows/2,cols/2),45,1)
rotation=cv2.warpAffine(img,M,(cols,rows))
cv_show('rotation',rotation)

points1=np.float32([[100,50],[100,200],[300,50]])            # affine
points2=np.float32([[150,100],[150,250],[350,100]])
M=cv2.getAffineTransform(points1,points2)
affine=cv2.warpAffine(img,M,(cols,rows))
cv_show('affine',affine)


pts1=np.float32([[100,50],[100,200],[300,50],[300,200]])            # perspective
pts2=np.float32([[150,100],[150,250],[350,100],[350,250]])
M=cv2.getPerspectiveTransform(pts1,pts2)
perspective=cv2.warpPerspective(img,M,(cols,rows))
cv_show('per',perspective)

全局阈值与位计算

掩膜

bg.jpg                                                                                   cvlogo.JPG

      opencv-python 教程整理_第1张图片

from matplotlib import pyplot as plt
import cv2 as cv
import numpy as np

img=cv.imread(cv.samples.findFile('bg.jpg'))
logo=cv.imread(cv.samples.findFile('cvlogo.JPG'))
rows,cols,channels=logo.shape
roi=img[200:200+rows,200:200+cols]

logogray=cv.cvtColor(logo, cv.COLOR_BGR2GRAY)
ret,mask=cv.threshold(logogray, 27, 255, cv.THRESH_BINARY)
mask_inv=cv.bitwise_not(mask)
roi_bg=cv.bitwise_and(roi, roi,mask=mask_inv)
logo_bg=cv.bitwise_and(logo,logo,mask=mask)
result=cv.add(roi_bg, logo_bg)

img[200:200+rows,200:200+cols]=result       
cv.imshow('img',roi_bg)
cv.imshow('logo',logo_bg)
cv.imshow('res',img)

cv.waitKey(0)
cv.destroyAllWindows()

                                    

使用自适应阈值:当同一幅图像上的不同部分具有不同亮度时

import cv2 as cv
from matplotlib import pyplot as plt
import numpy as np
img=cv.imread('bg.jpg')
a=cv.adaptiveThreshold(img,255,cv.ADAPTIVE_THRESH_MEAN_C,cv.THRESH_BINARY,blockSize=11,c=2)
#blocksize 邻域大小 C 常数  cv.ADAPTIVE_THRESH_MEAN_C 阈值取相邻区域的平均值
b=cv.adaptiveThreshold(img,255,cv.ADAPTIVE_THRESH_GAUSSIAN_C,cv.THRESH_BINARY,blockSize=11,c=2) 
#cv.ADAPTIVE_THRESH_GAUSSIAN_C 阈值取相邻区域的加权和,权重为一个高斯窗口

ret2,th2 = cv2.threshold(img,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)

#在使用全局阈值时,我们就是随便给了一个数来做阈值,那我们怎么知道我们选取的这个数的好坏呢?答案就是
#不停的尝试。如果是一副双峰图像(简单来说双峰图像是指图像直方图中存在两个峰)呢?我们岂不是应该在两
#个峰之间的峰谷选一个值作为阈值?这就是Otsu 二值化要做的。简单来说就是对一副双峰图像自动根据其直方
#图计算出一个阈值。(对于非双峰图像,这种方法得到的结果可能会不理想)

plt.hist(img.ravel(),256) # plt.hist, 要注意的是它的参数是一维数组
# 所以这里使用了(numpy)ravel 方法,将多维数组转换成一维,也可以使用flatten 方法
plt.imshow() 

 

图像平滑/图像模糊(2D卷积)

使用低通滤波器可以达到图像模糊的目的。这对与去除噪音很有帮助。其实就是去除图像中的高频成分(比如:噪音,边界)。所以边界也会被模糊一点。(当然,也有一些模糊技术不会模糊掉边界)

import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
from PIL import  Image
#img=Image.open('bg.jpg')
img=cv.imread('bg.jpg')
img=cv.cvtColor(img,cv.COLOR_BGR2RGB)
kernel=np.ones((5,5),dtype=np.float32)/25
out=cv.filter2D(img,-1,kernel) #-1 表示图片深度和原图像一样


plt.subplot(121),plt.imshow(img),plt.title('img')
plt.subplot(122),plt.imshow(out),plt.title('out')
plt.xticks([]),plt.yticke([])
plt.imshow()

#src.depth() = CV_8U, ddepth = -1/CV_16S/CV_32F/CV_64F
#src.depth() = CV_16U/CV_16S, ddepth = -1/CV_32F/CV_64F
#src.depth() = CV_32F, ddepth = -1/CV_32F/CV_64F
#src.depth() = CV_64F, ddepth = -1/CV_64F
#when ddepth=-1, the output image will have the same depth as the source.

opencv提供了四种模糊技术

cv2.blur(img,(5,5)) #均值滤波

cv2.medianBlur(img,5) #中值滤波  

cv2.GaussianBlur(img,(5,5),0) #高斯滤波 高斯核 标准差 高斯模糊 如果标准差为0 表示均值滤波
#高斯滤波器是求中心点邻近区域像素的高斯加权平均值。这种高斯滤波器只考虑像素之间的空
#间关系,而不会考虑像素值之间的关系(像素的相似度)。所以这种方法不会考
#虑一个像素是否位于边界。因此边界也会别模糊掉,而这正不是我们想要

cv2.bilateralFilter() #双边滤波  能在保持边界清晰的情况下有效的去除噪音。双边滤波在同时使用空间高
#斯权重和灰度值相似性高斯权重。空间高斯函数确保只有邻近区域的像素对中心点有影响,灰度值相似性高斯函
#数确保只有与中心像素灰度值相近的才会被用来做模糊运算。所以这种方法会确保边界不会被模糊掉,因为边界处#的灰度值变化比较大。

blur = cv2.bilateralFilter(img,9,75,75) # 9 #邻域直径,两个75 分别是空间高斯函数标准差,灰度值
#相似性高斯函数标准差

高斯函数,用于表述正态分布

高斯模糊(高斯滤波)的原理与算法

https://blog.csdn.net/nima1994/article/details/79776802

形态学转换(在图像处理中非常有用) 

形态学操作是根据图像形状进行的简单操作。一般情况下对二值化图像进行的操作。需要输入两个参数,一个是原始图像,第二个被称为结构化元素或核,它是用来决定操作的性质的

1.腐蚀

就像土壤侵蚀一样,这个操作会把前景物体的边界腐蚀掉(但是前景仍然是白色)。这是怎么做到的呢?卷积核沿着图像滑动,如果与卷积核对应的原图像的所有像素值都是1,那么中心元素就保持原来的像素值,否则就变为零。这会产生什么影响呢?根据卷积核的大小靠近前景的所有像素都会被腐蚀掉(变为0),所以前景物体会变小,整幅图像的白色区域会减少。这对于去除白噪声很有用,也可以用来断开两个连在一块的物体等。

2.膨胀 与之相反

与腐蚀相反,与卷积核对应的原图像的像素值中只要有一个是1,中心元素的像素值就是1。所以这个操作会增加图像中的白色区域(前景)。一般在去噪声时先用腐蚀再用膨胀。因为腐蚀在去掉白噪声的同时,也会使前景对象变小。所以我们再对他进行膨胀。这时噪声已经被去除了,不会再回来了,但是前景还在并会增加。膨胀也可以用来连接两个分开的物体。

import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
img=cv.imread('cvlogo.JPG',0)
ret ,thres=cv.threshold(img,25,255,cv.THRESH_BINARY)
kernel=np.ones((5,5),dtype=np.uint8)
erosion=cv.erode(thres,kernel,iterations=1)
dilate=cv.dilate(thres,kernel,iterations=1)
cv.imshow('erode',erosion)
cv.imshow('dilate',dilate)
cv.waitKey(0)
cv.destroyAllWindows()

开运算

先进行腐蚀再进行膨胀就叫做开运算。就像我们上面介绍的那样,它被用来去除噪声。

opening=cv.morphologyEx(thres,cv.MORPH_OPEN,kernel)

闭运算

先膨胀再腐蚀。它经常被用来填充前景物体中的小洞,或者前景物体上的小黑点。

opening=cv.morphologyEx(thres,cv.MORPH_CLOSE,kernel)

形态学梯度

其实就是一幅图像膨胀与腐蚀的差别。结果看上去就像前景物体的轮廓

opening=cv.morphologyEx(thres,cv.MORPH_GRADIENT,kernel)

礼帽

原始图像与进行开运算之后得到的图像的差 可以提亮某些部分

opening=cv.morphologyEx(thres,cv.MORPH_TOPHAT,kernel)

黑帽

进行闭运算之后得到的图像与原始图像的

opening=cv.morphologyEx(thres,cv.MORPH_BLACKHAT,kernel)

结构化元素 设置不同形状的核  这个很有用 可以自己修改kernel 当然也可以用np手动创建数组

cv.getStructuringElement(cv.MORPH_RECT,(5,5)) #方形kernel

cv.getStructuringElement(cv.MORPH_ELLIPSE,(5,5))

cv.getStructuringElement(cv.MORPH_CROSS,(5,5))

开运算:先腐蚀,再膨胀  可以清除一些小东西(亮的),放大局部低亮度的区域

闭运算:先膨胀,再腐蚀 可以清除小黑点

形态学梯度:膨胀图与腐蚀图之差   提取物体边缘

顶帽:原图像 - 开运算图   突出原图像中比周围亮的区域

黑帽:闭运算图 - 原图像    突出原图像中比周围暗的区域

 

高通滤波器 sobel scharr laplacian

EasyPR--开发详解(3)高斯模糊、灰度化和Sobel算子

http://www.bubuko.com/infodetail-409331.html  建议我的朋友们看看这篇文章的图形化讲解,理解sobel的重要性

Sobel 算子是高斯平滑与微分操作的结合体,所以它的抗噪声能力很好。你可以设定求导的方向(xorder 或yorder)。还可以设定使用的卷积核的大小(ksize)。值得一提的是 使用sobel函数 需要先将图片转化为灰度图 。

sobel,scharr是求一阶导数,由于图像是离散的,所有不是传统意义上的求一阶导数

                                opencv-python 教程整理_第2张图片

                                                  opencv-python 教程整理_第3张图片

          opencv-python 教程整理_第4张图片

如果ksize=-1,会使用3x3 的Scharr 滤波器,它的的效果要比3x3 的Sobel 滤波器好(而且速度相同,所以在使用3x3 滤波器时应该尽量使用Scharr 滤波器),scharr卷积核如下

 

                 opencv-python 教程整理_第5张图片 

 拉普拉斯滤波器使用的卷积核:

                                     opencv-python 教程整理_第6张图片

      opencv-python 教程整理_第7张图片                                  

  • 一阶导数提取出来的边缘较粗,
  • 二阶导数对细节更敏感, 如细线, 噪声等. 它提取出来的边缘更细更强(sharp)
  • 二阶导数的符号可用来判断一个转变(transition)是从亮到暗或者相反.
  • 应用二阶导数时容易出现double-line effect. (中间位置的二阶导数值与两边的往往不同). 出现双线效应的前提是线本身的宽度小于mask, 否则就不当作线, 而是region了.(见10.2.3)

 

import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt

img=cv.imread('bg.jpg',0)
img1=cv.Sobel(img,cv.CV_64F, 1, 0,ksize=5)  #sobel  # CV_64F 输出图像的深度(数据类型)如果不用-1的话,保持原来的
img4=cv.Sobel(img,cv.CV_64F,1,1,ksize=3)
img2=cv.Sobel(img,cv.CV_64F,0,1,ksize=-1)   #scharr
img3=cv.Laplacian(img,cv.CV_64F)            #laplacian

#如果原图像的深度是np.int8 时,所有的负值都会被截断变成0,换句话说就是把把边界丢失掉。
#所以如果这两种边界你都想检测到,最好的的办法就是将输出的数据类型设置的更高,比如cv2.CV_16S,#cv2.CV_64F 等。取绝对值然后再把它转回到cv2.CV_8U。下面的示例演示了输出图片的深度不同造成的不同效

 在查看上面这个例子的注释时不知道你有没有注意到:当我们可以通过参数-1 来设定输出图像的深度(数据类型)与原图像保持一致,但是我们在代码中使用的却是cv2.CV_64F。这是为什么呢?想象一下一个从黑到白的边界的导数是整数,而一个从白到黑的边界点导数却是负数。如果原图像的深度是np.int8 时,所有的负值都会被截断变成0,换句话说就是把把边界丢失掉。所以如果这两种边界你都想检测到,最好的的办法就是将输出的数据类型设置的更高,比如cv2.CV_16S,cv2.CV_64F 等。取绝对值然后再把它转回到cv2.CV_8U。

 

Canny 边缘检测

Canny 边缘检测是一种非常流行的边缘检测算法,它是一个有很多步构成的算法

1.用5*5的高斯滤波器去除噪声

2.用sobel x,y方向计算图像梯度,梯度方向 tan^(-1) (Gx/Gy)

3.NMS 非极大值抑制

4.滞后阈值

我们需要设置两个阈值:minVal 和maxVal。当图像的灰度梯度高于maxVal 时被认为是真的边界,那些低于minVal 的边界会被抛弃。如果介于两者之间的话,就要看这个点是否与某个被确定为真正的边界点相连,如果是就认为它也是边界点,如果不是就抛弃。

 

                                               opencv-python 教程整理_第8张图片

                                            

img=cv.Canny(img,50,150)

 

图像金字塔 可以用来做图像融合 SIFT算法

数字图像处理(21): 图像金字塔(高斯金字塔 与 拉普拉斯金字塔)

这篇文章讲得很好惹

import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
img=cv.imread('cvlogo.JPG')
down=cv.pyrDown(img)
up=cv.pyrUp(down)
cv.imshow('img',down)
cv.imshow('up',up)
cv.waitKey(0)
cv.destroyAllWindows()

轮廓

轮廓可以简单认为成将连续的点(连着边界)连在一起的曲线,具有相同的颜色或者灰度。轮廓在形状分析和物体的检测和识别中很有用。

import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
img1=cv.imread('logo.JPG')
img=cv.cvtColor(img1, cv.COLOR_BGR2GRAY)
ret,thre=cv.threshold(img, 175, 255, 0)
contours,hierarchy=cv.findContours(thre,cv.RETR_TREE,cv.CHAIN_APPROX_SIMPLE)
out=cv.drawContours(img1,contours,-1,(0,200,255),2) #画轮廓的图一定是三通道图
cv.imshow('img',thre)
cv.imshow('out',out)
cv.waitKey(0)
cv.destroyAllWindows()
import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
bg=np.ones((553,295,3),dtype=np.uint8)*255
img=cv.imread('knife.JPG')
imggray=cv.cvtColor(img.copy(), cv.COLOR_BGR2GRAY)
mask=cv.threshold(imggray, 175, 255, 0)[1]
mask_inv=cv.bitwise_not(mask)
bg_white=cv.bitwise_and(bg,bg,mask=mask)
get=cv.add(bg_white,img)

contours=cv.findContours(mask,cv.RETR_TREE,cv.CHAIN_APPROX_SIMPLE)[0]
out=cv.drawContours(get,contours,1,(255,200,0),2)


plt.subplot(121),plt.imshow(img),plt.title('img')
plt.xticks([]),plt.yticks([])
plt.subplot(122),plt.imshow(out),plt.title('out')
plt.xticks([]),plt.yticks([])
plt.show()

                                    opencv-python 教程整理_第9张图片

形状识别

 

                                             opencv-python 教程整理_第10张图片

import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
bg=np.ones((553,295,3),dtype=np.uint8)*255
img=cv.imread('shape.jpg')
imgcnt=img.copy()
imggray=cv.cvtColor(img.copy(), cv.COLOR_BGR2GRAY)
imggray=cv.GaussianBlur(imggray, (5,5),0)
mask=cv.threshold(imggray, 240, 255, 0)[1]

cnts=cv.findContours(mask,cv.RETR_TREE,cv.CHAIN_APPROX_SIMPLE)[0]
for i,cnt in enumerate(cnts[1:]):
	#cv.drawContours(imgcnt,cnt,-1 ,(255,200,0),2)
	area=cv.contourArea(cnt)
	perimeter=cv.arcLength(cnt,True)
	approx=cv.approxPolyDP(cnt,0.02*perimeter,True)
	x,y,w,h = cv.boundingRect(approx)
	cv.rectangle(imgcnt,(x,y) , (x+w,y+h), (255,0,0),1)
	if len(approx)==3:
		
		cv.putText(imgcnt,'Triangle',(x+(w//2)-40,y+(h//2)),cv.FONT_HERSHEY_COMPLEX,0.5,(0,0,0),1)
	elif len(approx)==4: 
		ratio = w/float(h)
		if ratio>0.95 and ratio<1.05:
			cv.putText(imgcnt,'Squar',(x+(w//2)-40,y+(h//2)),cv.FONT_HERSHEY_COMPLEX,0.5,(0,0,0),1)
		else:
			cv.putText(imgcnt,'Rectangle',(x+(w//2)-40,y+(h//2)),cv.FONT_HERSHEY_COMPLEX,0.5,(0,0,0),1)
	elif len(approx) >4:
			cv.putText(imgcnt,'Circle',(x+(w//2)-40,y+(h//2)),cv.FONT_HERSHEY_COMPLEX,0.5,(0,0,0),1)
	 

cv.imshow('out',imgcnt)
cv.waitKey(0)
cv.destroyAllWindows()  

                                      opencv-python 教程整理_第11张图片

摄像头实时检测形状:结果效果 很垃圾 ,根本不实用,只能检测到正正规规的东西

import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
cap=cv.VideoCapture(0)
cap.set(3,640)
cap.set(4,480)
if cap.isOpened():
	ret,frame=cap.read()
	while ret:
		ret,frame=cap.read()
		imgcnt=frame.copy()
		imggray=cv.cvtColor(frame.copy(), cv.COLOR_BGR2GRAY)
		imggray=cv.GaussianBlur(imggray, (5,5),0)
		mask=cv.threshold(imggray, 240, 255, 0)[1]
		cnts=cv.findContours(mask,cv.RETR_TREE,cv.CHAIN_APPROX_SIMPLE)[0]
		for i,cnt in enumerate(cnts[1:]):
	#cv.drawContours(imgcnt,cnt,-1 ,(255,200,0),2)
			area=cv.contourArea(cnt)
			if area >1000:
				perimeter=cv.arcLength(cnt,True)
				approx=cv.approxPolyDP(cnt,0.02*perimeter,True)
				x,y,w,h = cv.boundingRect(approx)
				cv.rectangle(imgcnt,(x,y) , (x+w,y+h), (255,0,0),1)
				if len(approx)==3:
			
					cv.putText(imgcnt,'Triangle',(x+(w//2)-40,y+(h//2)),cv.FONT_HERSHEY_COMPLEX,0.5,(0,0,0),1)
				elif len(approx)==4: 
					ratio = w/float(h)
					if ratio>0.95 and ratio<1.05:
						cv.putText(imgcnt,'Squar',(x+(w//2)-40,y+(h//2)),cv.FONT_HERSHEY_COMPLEX,0.5,(0,0,0),1)
					else:
						cv.putText(imgcnt,'Rectangle',(x+(w//2)-40,y+(h//2)),cv.FONT_HERSHEY_COMPLEX,0.5,(0,0,0),1)
				elif len(approx) >4:
					cv.putText(imgcnt,'Circle',(x+(w//2)-40,y+(h//2)),cv.FONT_HERSHEY_COMPLEX,0.5,(0,0,0),1)
	 

		cv.imshow('out',imgcnt)
		if cv.waitKey(1) & 0xFF ==ord('q'):
			break
cap.release()
cv.destroyAllWindows()  

 

 

 

HSV通道 trackerbar 调参数

import cv2
import numpy as np 

def nothing(x):
	pass

cap=cv2.VideoCapture(0)
cap.set(3,640)
cap.set(4,480)

cv2.namedWindow('HSV')
cv2.resizeWindow('HSV', 640, 480)
cv2.createTrackbar('Hmin','HSV',0,179,nothing)
cv2.createTrackbar('Hmax','HSV',19,179,nothing)
cv2.createTrackbar('Smin','HSV',110,255,nothing)
cv2.createTrackbar('Smax','HSV',240,255,nothing)
cv2.createTrackbar('Vmin','HSV',153,255,nothing)
cv2.createTrackbar('Vmax','HSV',255,255,nothing)

if cap.isOpened():
	ret ,frame = cap.read()
	while ret :
		ret ,frame1 = cap.read()	
		frame=cv2.GaussianBlur(frame1,(5,5),0)
		f_hsv=cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
		hmin=cv2.getTrackbarPos('Hmin', 'HSV')
		hmax=cv2.getTrackbarPos('Hmax', 'HSV')
		smin=cv2.getTrackbarPos('Smin', 'HSV')
		smax=cv2.getTrackbarPos('Smax', 'HSV')
		vmin=cv2.getTrackbarPos('Vmin', 'HSV')
		vmax=cv2.getTrackbarPos('Vmax', 'HSV')
		lower = np.array([hmin,smin,vmin])
		upper = np.array([hmax,smax,vmax])
		'''lower = np.array([0,43,255])
		upper = np.array([46,255,255])'''
		mask = cv2.inRange(f_hsv,lower,upper)
		out = cv2.bitwise_and(frame,frame,mask=mask)
		
		cv2.imshow('mask',mask)
		cv2.imshow('Blur',frame1)
		cv2.imshow('HSV',out)
		if cv2.waitKey(1) & 0xFF ==ord('q'):
			break;
		
	cap.release()
	cv2.destroyAllWindows()

旋转的边界矩形这个边界矩形是面积最小的,因为它考虑了对象的旋转。用到的函数为cv2.minAreaRect()。返回的是一个Box2D 结构,其中包含矩形左上角角点的坐标(x,y),矩形的宽和高(w,h),以及旋转角度。但是要绘制这个矩形需要矩形的4 个角点,可以通过函数cv2.boxPoints() 获得。

HSV颜色识别  多种颜色

import cv2
import numpy as np 

def nothing(x):
	pass

cap=cv2.VideoCapture(0)
cap.set(3,640)
cap.set(4,480)

cv2.namedWindow('HSV')
cv2.resizeWindow('HSV', 640, 480)
cv2.createTrackbar('Hmin','HSV',0,179,nothing)
cv2.createTrackbar('Hmax','HSV',19,179,nothing)
cv2.createTrackbar('Smin','HSV',110,255,nothing)
cv2.createTrackbar('Smax','HSV',240,255,nothing)
cv2.createTrackbar('Vmin','HSV',153,255,nothing)
cv2.createTrackbar('Vmax','HSV',255,255,nothing)

if cap.isOpened():
	ret ,frame = cap.read()
	while ret :
		ret ,frame1 = cap.read()	
		frame=cv2.GaussianBlur(frame1,(5,5),0)
		f_hsv=cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
		hmin=cv2.getTrackbarPos('Hmin', 'HSV')
		hmax=cv2.getTrackbarPos('Hmax', 'HSV')
		smin=cv2.getTrackbarPos('Smin', 'HSV')
		smax=cv2.getTrackbarPos('Smax', 'HSV')
		vmin=cv2.getTrackbarPos('Vmin', 'HSV')
		vmax=cv2.getTrackbarPos('Vmax', 'HSV')
		lower = np.array([hmin,smin,vmin])
		upper = np.array([hmax,smax,vmax])
		lower = np.array([[0,106,245],[19,185,115]])
		upper = np.array([[179,255,255],[179,255,255]])
		mask1 = cv2.inRange(f_hsv,lower[0],upper[0])
		mask2 = cv2.inRange(f_hsv,lower[1],upper[1])
		out1 = cv2.bitwise_and(frame,frame,mask=mask1)
		out2 = cv2.bitwise_and(frame,frame,mask=mask2)
		cnt1s=cv2.findContours(mask1,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)[0]
		cnt2s=cv2.findContours(mask2,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)[0]
		
		for cnt2 in cnt2s :			
			area2=cv2.contourArea(cnt2)
			if area2>2000:
				cv2.drawContours(frame1,cnt2,-1,(0,0,255),2)
				
		for cnt1 in cnt1s:
			area1=cv2.contourArea(cnt1)
			if area1 >2000:
				cv2.drawContours(frame1,cnt1,-1,(255,0,0),2)
			
		cv2.imshow('mask1',mask1)
		cv2.imshow('mask2',mask2)
		cv2.imshow('result',frame1)		
		if cv2.waitKey(1) & 0xFF ==ord('q'):
			break;
		
	cap.release()
	cv2.destroyAllWindows()

                     opencv-python 教程整理_第12张图片

车牌检测

import cv2
import numpy as np 
roi=[]
label={}
target=[]
img=cv2.imread('ocr_a_reference.png')
img_gray=cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
img_bit=cv2.threshold(img_gray,10,255,cv2.THRESH_BINARY_INV)[1]
cnts=cv2.findContours(img_bit,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)[0]
#cv2.imshow('bit',img_bit)
#cv2.waitKey(0)
for i,cnt in enumerate(cnts):
	x,y,w,h = cv2.boundingRect(cnt)
	cv2.rectangle(img, (x,y), (x+w,y+h), (255,0,0),2)
	original=img[y:y+h,x:x+w]
	resize=cv2.resize(original, (57, 88))
	roi.append(resize)
	#cv2.imshow('img',roi[i])
	#cv2.waitKey(0)
	
roi.reverse()

for i,r in enumerate(roi):
	label[i]={str(i):r}
	#cv2.imshow('img',roi[i])
	#cv2.waitKey(0)
kernel=np.ones((3,3))	
rectKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (20, 3)) #非常灵活 非常有用

card = cv2.imread('./images/credit_card_01.png')
card_gray = cv2.cvtColor(card,cv2.COLOR_BGR2GRAY)
#card_bit=cv2.threshold(card, 175, 255, cv2.THRESH_BINARY)[1]
card_bit=cv2.threshold(card_gray, 0, 255,cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]
#tophat = cv2.morphologyEx(card_bit,cv2.MORPH_TOPHAT, rectKernel) 
gradX = cv2.Sobel(card_bit, ddepth=cv2.CV_64F, dx=1, dy=0, #ksize=-1相当于用3*3的
	ksize=5)
#sobelx=cv2.Sobel(tophat,cv2.CV_32F,1,0,ksize =-1)
sobelx=np.absolute(gradX)
sobelx=np.uint8(sobelx)
#(minVal, maxVal) = (np.min(sobelx), np.max(sobelx))
#sobelx = (255 * (sobelx - minVal) / (maxVal - minVal))
#sobelx = sobelx.astype("uint8")
close=cv2.morphologyEx(sobelx,cv2.MORPH_CLOSE,rectKernel)
#close=cv2.morphologyEx(close,cv2.MORPH_CLOSE,kernel)
#dilate=cv2.dilate(close,kernel,iterations=1)

#cv2.imshow('tophat',tophat)
#cv2.imshow('sobelx',sobelx)
#cv2.imshow('close',close)
cnts = cv2.findContours(close.copy(),cv2.RETR_EXTERNAL,\
	cv2.CHAIN_APPROX_SIMPLE)[0]
store=[]
i=0
for cnt in cnts:
	area=cv2.contourArea(cnt)
	perimeter=cv2.arcLength(cnt, True)
	approx=cv2.approxPolyDP(cnt,0.02*perimeter, True)		
	x,y,w,h=cv2.boundingRect(approx)
	ratio=w/float(h)
	if (ratio>2.5) & (ratio <4) :
		if (w > 90 and w < 150) and (h > 25 and h < 40):
			store.insert(i,(x,y,w,h))
			i += 1
			#cv2.rectangle(card, (x,y), (x+w,y+h), (0,0,255),2)

		
#store=np.asarray(store,dtype=np.uint8)			
store.sort(key=lambda x:x[0])	
		
for i,get in enumerate(store):
	x,y,w,h =get
	cv2.rectangle(card, (x,y), (x+w,y+h), (0,0,255),2)
	target.append(card[y:y+h,x:x+w])
	cv2.imshow('slice',target[i])
	cv2.waitKey(0)
				
	
	
#cv2.drawContours(card,cnts,-1,(0,0,255),2)
cv2.imshow('card',card)
	
cv2.waitKey(0)
cv2.destroyAllWindows()








'''		if cv2.waitKey(1) & 0xFF ==ord('q'):
			break;
		
	cap.release()
	cv2.destroyAllWindows()'''

仿射变换 和透视变换 例子

opencv-python 教程整理_第13张图片

import cv2
import numpy as np


def cv_show(name,img):
	cv2.imshow(name, img)
	cv2.waitKey(0)
	cv2.destroyAllWindows()

def order_points(pts):
	# 一共4个坐标点
	rect = np.zeros((4, 2), dtype = "float32")

	# 按顺序找到对应坐标0123分别是 左上,右上,右下,左下
	# 计算左上,右下
	s = pts.sum(axis = 1)
	#print(s)
	rect[0] = pts[np.argmin(s)]
	rect[2] = pts[np.argmax(s)]

	# 计算右上和左下
	diff = np.diff(pts, axis = 1)
	rect[1] = pts[np.argmin(diff)]
	rect[3] = pts[np.argmax(diff)]
	return rect

def four_point_transform(img,pts):
	# 获取输入坐标点
	rect = order_points(pts)
	(tl, tr, br, bl) = rect

	# 计算输入的w和h值
	widthA=np.sqrt(((tl[0]-tr[0])**2)+(tl[1]-tr[1])**2)
	widthB=np.sqrt(((bl[0]-br[0])**2)+((bl[1]-br[1])**2))
	maxWidth = max(int(widthA), int(widthB))
	
	heightA=np.sqrt(((tl[0]-bl[0])**2)+((tl[1]-bl[1])**2))
	heightB=np.sqrt(((tr[0]-br[0])**2)+((tr[1]-br[1])**2))
	maxHeight = max(int(heightA), int(heightB))
	
	
	
	new=np.asarray([[0,0],[maxWidth,0],[maxWidth,maxHeight],[0,maxHeight]],dtype= "float32")
	
	M=cv2.getPerspectiveTransform(rect,new)
	warped=cv2.warpPerspective(img,M,(maxWidth,maxHeight))
	
	return warped
	
img=cv2.imread(cv2.samples.findFile('./images/example_test.png'))
contours_img = img.copy()

img_gray=cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
img_blur=cv2.GaussianBlur(img_gray,(5,5), 0)
img_canny=cv2.Canny(img_blur, 75, 200)
cnts = cv2.findContours(img_canny,cv2.RETR_EXTERNAL,\
	cv2.CHAIN_APPROX_SIMPLE)[0]

cv2.drawContours(contours_img, cnts, -1, (0,0,255),3)	
cv_show('img',contours_img)

if len(cnts)>0:
	
	for cnt in cnts:
		L=cv2.arcLength(cnt,True)
		approx = cv2.approxPolyDP(cnt, 0.02 * L, True)
		#print(len(approx))
		if len(approx) ==4 :
			points=approx.reshape(4,2)
			#print(points.shape)
			warped=four_point_transform(img_gray,points)
			cv_show('warped',warped)

三个点的 二维 仿射变换, 四个点的 三维 透视变换

实时视频实现

mport cv2
import numpy as np


def cv_show(name,img):
	cv2.imshow(name, img)
	cv2.waitKey(1)
	#cv2.destroyAllWindows()

def order_points(pts):
	# 一共4个坐标点
	rect = np.zeros((4, 2), dtype = "float32")

	# 按顺序找到对应坐标0123分别是 左上,右上,右下,左下
	# 计算左上,右下
	s = pts.sum(axis = 1)
	#print(s)
	rect[0] = pts[np.argmin(s)]
	rect[2] = pts[np.argmax(s)]

	# 计算右上和左下
	diff = np.diff(pts, axis = 1)
	rect[1] = pts[np.argmin(diff)]
	rect[3] = pts[np.argmax(diff)]
	return rect

def four_point_transform(img,pts):
	# 获取输入坐标点
	rect = order_points(pts)
	(tl, tr, br, bl) = rect

	# 计算输入的w和h值
	widthA=np.sqrt(((tl[0]-tr[0])**2)+(tl[1]-tr[1])**2)
	widthB=np.sqrt(((bl[0]-br[0])**2)+((bl[1]-br[1])**2))
	maxWidth = max(int(widthA), int(widthB))
	
	heightA=np.sqrt(((tl[0]-bl[0])**2)+((tl[1]-bl[1])**2))
	heightB=np.sqrt(((tr[0]-br[0])**2)+((tr[1]-br[1])**2))
	maxHeight = max(int(heightA), int(heightB))
	
	
	
	new=np.asarray([[0,0],[maxWidth,0],[maxWidth,maxHeight],[0,maxHeight]],dtype= "float32")
	
	M=cv2.getPerspectiveTransform(rect,new)
	warped=cv2.warpPerspective(img,M,(maxWidth,maxHeight))
	
	return warped

cap=cv2.VideoCapture(0)	
ret ,frame=cap.read()
while ret:
	ret ,frame=cap.read()
	#img=cv2.imread(cv2.samples.findFile('./images/example_test.png'))
	contours_img = frame.copy()
	
	img_gray=cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
	img_blur=cv2.GaussianBlur(img_gray,(5,5), 0)
	img_canny=cv2.Canny(img_blur, 75, 200)
	cnts = cv2.findContours(img_canny,cv2.RETR_EXTERNAL,\
		cv2.CHAIN_APPROX_SIMPLE)[0]
	
	cv2.drawContours(contours_img, cnts, -1, (0,0,255),3)	
	cv_show('img',contours_img)

	if len(cnts)>0:
		
		for cnt in cnts:
			L=cv2.arcLength(cnt,True)
			approx = cv2.approxPolyDP(cnt, 0.02 * L, True)
			#print(len(approx))
			if len(approx) ==4 :
				points=approx.reshape(4,2)
				#print(points.shape)
				warped=four_point_transform(img_gray,points)
				cv_show('warped',warped)

cap.release()
cv2.destroyAllWindows()

直方图部分 先省略不写

 

np.hstack  np.vstack

傅里叶变换

OpenCV学习笔记-傅里叶变换   教会我用mask 配合傅里叶变化做高通低通滤波器

这篇文章写得挺好的

下面的图是频谱图的解释,中间的光亮部分代表频率为0的部分 也就是直流量

 模板匹配  可以做物体/人脸之类的识别

res = cv2.matchTemplate(img,template,method)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)

Hough霍夫直线变换

霍夫变换检测直线的应用

 

 

 

                                 opencv-python 教程整理_第14张图片

主要公式推导 

                               opencv-python 教程整理_第15张图片

                             opencv-python 教程整理_第16张图片 

累加器 计数 

OpenCV中HoughLines检测直线原理图解 画线时点的确定:为什么要乘以1000 画出所有直线 Python代码实现

 

cv2.HoughLines()

import cv2 
import numpy as np
from matplotlib import pyplot as plt 

img=cv2.imread('bg.jpg',0)
canny=cv2.Canny(img,100,200)
lines=cv2.HoughLines(canny,1,np.pi/180,200)
lines=np.reshape(lines,(-1,2))
for rho,theta in lines :
	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)) 
	cv2.line(img,(x1,y1),(x2,y2),(0,0,255),1)

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

Probabilistic Hough Transform  仅仅是一条直线都需要两个参数,这需要大量的计算。Probabilistic_Hough_Transform 是对霍夫变换的一种优化

import cv2 
import numpy as np
from matplotlib import pyplot as plt 
def cv_show(name,img):
	cv2.imshow(name, img)
	cv2.waitKey(0)
	#cv2.destroyAllWindows()

img=cv2.imread('bg.jpg')
img_gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
canny=cv2.Canny(img_gray,150,200)
minLineLength = 50
maxLineGap = 10
lines = cv2.HoughLinesP(canny,1,np.pi/180,50,minLineLength,maxLineGap)
for x1,y1,x2,y2 in lines[0]:
	cv2.line(img,(x1,y1),(x2,y2),(0,255,0),2)

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

分水岭算法图像分割

chap7-watershed   这个视频讲解得很好

Harris 角点检测 

4.harris corner detection(角点检测)

 

你可能感兴趣的:(计算机视觉,opencv,python)