应该记住的是图像的宽对应的是列数,高对应的是行数。
读取图片
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
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))
开运算:先腐蚀,再膨胀 可以清除一些小东西(亮的),放大局部低亮度的区域
闭运算:先膨胀,再腐蚀 可以清除小黑点
形态学梯度:膨胀图与腐蚀图之差 提取物体边缘
顶帽:原图像 - 开运算图 突出原图像中比周围亮的区域
黑帽:闭运算图 - 原图像 突出原图像中比周围暗的区域
EasyPR--开发详解(3)高斯模糊、灰度化和Sobel算子
http://www.bubuko.com/infodetail-409331.html 建议我的朋友们看看这篇文章的图形化讲解,理解sobel的重要性
Sobel 算子是高斯平滑与微分操作的结合体,所以它的抗噪声能力很好。你可以设定求导的方向(xorder 或yorder)。还可以设定使用的卷积核的大小(ksize)。值得一提的是 使用sobel函数 需要先将图片转化为灰度图 。
sobel,scharr是求一阶导数,由于图像是离散的,所有不是传统意义上的求一阶导数
如果ksize=-1,会使用3x3 的Scharr 滤波器,它的的效果要比3x3 的Sobel 滤波器好(而且速度相同,所以在使用3x3 滤波器时应该尽量使用Scharr 滤波器),scharr卷积核如下
拉普拉斯滤波器使用的卷积核:
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 的边界会被抛弃。如果介于两者之间的话,就要看这个点是否与某个被确定为真正的边界点相连,如果是就认为它也是边界点,如果不是就抛弃。
img=cv.Canny(img,50,150)
这篇文章讲得很好惹
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()
形状识别
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()
摄像头实时检测形状:结果效果 很垃圾 ,根本不实用,只能检测到正正规规的东西
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()
车牌检测
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()'''
仿射变换 和透视变换 例子
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
这篇文章写得挺好的
下面的图是频谱图的解释,中间的光亮部分代表频率为0的部分 也就是直流量
res = cv2.matchTemplate(img,template,method)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)
Hough霍夫直线变换
霍夫变换检测直线的应用
主要公式推导
累加器 计数
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(角点检测)