OpenCV案例教程(数字图像处理Python实现,含目录)

一、图像基本知识

1.读入图像

#导入opencv的python版本依赖库cv2
import cv2
#使用opencv中imread函数读取图片,
#0代表灰度图形式打开,1代表彩色形式打开
img = cv2.imread('split.jpg',1)
print(img.shape)
#print(img)

2.显示图像及保存图像

#导入opencv依赖库
import cv2
#读取图像,读取方式为彩色读取
img = cv2.imread('split.jpg',1)
#
cv2.imshow('photo',img)
k = cv2.waitKey(5000)
if k == 27:   # 输入ESC键退出
    cv2.destroyAllWindows()
elif k == ord('s'): # 输入S键保存图片并退出
    cv2.imwrite('split_.jpg',img)
cv2.destroyAllWindows()
#加载第三方包
import cv2
from matplotlib import pyplot as plt
#使用Matplotlib导入图像
img = cv2.imread('test_image.png',0)
plt.imshow(img, cmap = 'gray', interpolation = 'bicubic')
#隐藏X、Y轴上的刻度
plt.xticks([]), plt.yticks([])
plt.show()

3.通道转化,三通道转为单通道灰度图

#导入opencv
import cv2 
#读入原始图像,使用cv2.IMREAD_UNCHANGED
img = cv2.imread("girl.jpg",cv2.IMREAD_UNCHANGED)
#查看打印图像的shape
shape = img.shape
print(shape)
#判断通道数是否为3通道或4通道
if shape[2] == 3 or shape[2] == 4 :
    #将彩色图转化为单通道图
    img_gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
    cv2.imshow("gray_image",img_gray)
cv2.imshow("image", img)
cv2.waitKey(5000)
cv2.destroyAllWindows()

4.通道转化,单通道转为三通道灰度图

#导入opencv
import cv2 
#读入灰度图
img = cv2.imread("girl_gray.jpg",cv2.IMREAD_UNCHANGED)
#查看打印图像的shape
shape = img.shape
print(shape)
img_color = cv2.cvtColor(img,cv2.COLOR_GRAY2BGR)
print(img_color.shape)
cv2.imshow("color_image",img_color)
cv2.imshow("image", img)
cv2.waitKey(5000)
cv2.destroyAllWindows()

5.图像三通道分离

#加载opencv
import cv2
src=cv2.imread('split.jpg')
cv2.imshow('before',src)
#调用通道分离
b,g,r=cv2.split(src)
#三通道分别显示
cv2.imshow('blue',b)
cv2.imshow('green',g)
cv2.imshow('red',r)
cv2.waitKey(5000)
cv2.destroyAllWindows()
#导入opencv模块
import numpy as np
import cv2            
image=cv2.imread("split.jpg")#读取要处理的图片
cv2.imshow("src",image)
cv2.waitKey(5000)
B,G,R = cv2.split(image)#分离出图片的B,R,G颜色通道
zeros = np.zeros(image.shape[:2],dtype="uint8")#创建与image相同大小的零矩阵
cv2.imshow("BLUE",cv2.merge([B,zeros,zeros]))#显示 (B,0,0)图像
cv2.imshow("GREEN",cv2.merge([zeros,G,zeros]))#显示(0,G,0)图像
cv2.imshow("RED",cv2.merge([zeros,zeros,R]))#显示(0,0,R)图像
cv2.waitKey(5000)
cv2.destroyAllWindows()
print(image.shape[:2])
print(image.shape[1:])

6.图像通道合并

#加载opencv
import cv2
src=cv2.imread('split.jpg')
cv2.imshow('before',src)
#调用通道分离
b,g,r=cv2.split(src)
#将Blue通道数值修改为0
g[:] = 0
#合并修改后的通道
img_merge=cv2.merge([b,g,r])
cv2.imshow('merge',img_merge)
cv2.waitKey(5000)
cv2.destroyAllWindows()

7.通道分离与合并小结

import cv2 as cv
import numpy as np
src=cv.imread('split.jpg')
#cv.namedWindow('before',cv.WINDOW_NORMAL)
cv.imshow('before',src)
cv.waitKey(5000)
#通道分离
b,g,r=cv.split(src)
cv.imshow('blue',b)
cv.imshow('green',g)
cv.imshow('red',r)
cv.waitKey(5000)
#通道合并
src=cv.merge([b,g,r])
cv.imshow('merge',src)
cv.waitKey(5000)
# 修改某个通道
src[:,:,2]=100
cv.imshow('single',src)
cv.waitKey(5000)
cv.destroyAllWindows()

8.RGB与BGR转化

import cv2 
import matplotlib.pyplot as plt 
img = cv2.imread("test2.png", cv2.IMREAD_COLOR)
cv2.imshow("Opencv_win", img)
# 用opencv自带的方法转
img_cv_method = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
# 用numpy转,img[:,:,::-1]列左右翻转
img_numpy_method = img[:,:,::-1] # 本来是BGR 现在逆序,变成RGB
# 用matplot画图
plt.subplot(1,3,1)
plt.imshow(img_cv_method)
plt.subplot(1,3,2)
plt.imshow(img_numpy_method)
plt.subplot(1,3,3)
plt.imshow(img)
plt.savefig("./plt.png")
plt.show()
#保存图片
cv2.imwrite("opencv.png", img)
cv2.waitKey(5000)
cv2.destroyAllWindows()

9.RGB与HSV转化

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)
    #print(hsv)
    cv2.imshow('hsv',hsv)
#读入一张彩色图
src=cv2.imread('girl.jpg')
cv2.imshow('before',src)
#调用color_space_demo函数进行色彩空间转化
color_space_demo(src)
cv2.waitKey(0)
cv2.destroyAllWindows()

10.直方图绘制

#加载第三方库
from matplotlib import pyplot as plt
import cv2

girl = cv2.imread("girl.jpg")
cv2.imshow("girl", girl)
# girl.ravel()函数是将图像的三位数组降到一维上去,
#256为bins的数目,[0, 256]为范围
plt.hist(girl.ravel(), 256, [0, 256])
plt.show()
cv2.waitKey(5000)
cv2.destroyAllWindows()
from matplotlib import pyplot as plt
import cv2
import numpy as np
img = cv2.imread('girl.jpg')
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

plt.imshow(img_gray, cmap=plt.cm.gray)
hist = cv2.calcHist([img], [0], None, [256], [0, 256])

plt.figure()
plt.title("Grayscale Histogram")
plt.xlabel("Bins")
plt.ylabel("# of Pixels")
plt.plot(hist)
plt.xlim([0, 256])
plt.show()

11.三通道直方图绘制

from matplotlib import pyplot as plt
import cv2
girl = cv2.imread("girl.jpg")
cv2.imshow("girl", girl)
color = ("b", "g", "r")
#使用for循环遍历color列表,enumerate枚举返回索引和值
for i, color in enumerate(color):
    hist = cv2.calcHist([girl], [i], None, [256], [0, 256])
    plt.title("girl")
    plt.xlabel("Bins")
    plt.ylabel("num of perlex")
    plt.plot(hist, color = color)
    plt.xlim([0, 260])
plt.show()
cv2.waitKey(5000)
cv2.destroyAllWindows()

在这里插入图片描述

二、图像基本处理

1.第一节:基本操作

1.绘制线段

import numpy as np
import cv2

# 创建一张黑色的背景图
img=np.zeros((512,512,3), np.uint8)
cv2.imshow("black", img)
cv2.waitKey(5000)
cv2.destroyWindow("black")
# 绘制一条线宽为5的线段
cv2.line(img,(0,0),(200,500),(0,0,255),5)

winname = 'example'
cv2.namedWindow(winname)
cv2.imshow(winname, img)
cv2.waitKey(5000)
cv2.destroyWindow(winname)

2.绘制矩形

import numpy as np
import cv2

# 创建一张黑色的背景图
img=np.zeros((512,512,3), np.uint8)

# 画一个绿色边框的矩形,参数2:左上角坐标,参数3:右下角坐标
cv2.rectangle(img,(384,0),(510,128),(0,255,255),10)

winname = 'example'
cv2.namedWindow(winname)
cv2.imshow(winname, img)
cv2.waitKey(5000)
cv2.destroyWindow(winname)

3.绘制圆

import numpy as np
import cv2
# 创建一张黑色的背景图
img=np.zeros((512,512,3), np.uint8)
# 画一个填充红色的圆,参数2:圆心坐标,参数3:半径
cv2.circle(img,(447,63), 63, (0,0,255), -1)
winname = 'example'
cv2.namedWindow(winname)
cv2.imshow(winname, img)
cv2.waitKey(5000)
cv2.destroyWindow(winname)

4.绘制椭圆

import numpy as np
import cv2
# 创建一张黑色的背景图
img=np.zeros((512,512,3), np.uint8)
# 在图中心画一个填充的半圆
cv2.ellipse(img, (256, 256), (100, 50), 0, 30, 360, (255, 0, 0), -1)
winname = 'example'
cv2.namedWindow(winname)
cv2.imshow(winname, img)
cv2.waitKey(5000)
cv2.destroyWindow(winname)

5.绘制多边形

import numpy as np
import cv2
# 创建一张黑色的背景图
img=np.zeros((512,512,3), np.uint8)
# 定义四个顶点坐标
pts = np.array([[20, 15],  [60, 20], [80, 30], [230, 240]])
print(pts)
# 顶点个数:4,矩阵变成4*1*2维
pts = pts.reshape((-1, 1, 2))
print(pts)
#绘制椭圆
cv2.polylines(img, [pts], False, (0, 255, 255))
winname = 'example'
cv2.namedWindow(winname)
cv2.imshow(winname, img)
cv2.waitKey(5000)
cv2.destroyWindow(winname)

6.添加文字

import numpy as np
import cv2
# 创建一张黑色的背景图
img=np.zeros((512,512,3), np.uint8)
#添加文字
font=cv2.FONT_HERSHEY_SIMPLEX
cv2.putText(img,'OpenCV',(50,200), font, 3,(0,255,255),5)
winname = 'example'
cv2.namedWindow(winname)
cv2.imshow(winname, img)
cv2.waitKey(5000)
cv2.destroyWindow(winname)

7.综合图像绘制

import numpy as np
import cv2
# 创建一张黑色的背景图
img=np.zeros((512,512,3), np.uint8)
# 绘制一条线宽为5的线段
cv2.line(img,(0,0),(511,511),(255,0,0),1)
# 画一个绿色边框的矩形,参数2:左上角坐标,参数3:右下角坐标
cv2.rectangle(img,(384,0),(510,128),(0,255,0),3)
# 画一个填充红色的圆,参数2:圆心坐标,参数3:半径
cv2.circle(img,(447,63), 63, (0,0,255), -1)
# 在图中心画一个填充的半圆
cv2.ellipse(img, (256, 256), (100, 150), 10, 0, 180, (255, 0, 0), -1)
#绘制多边形
pts=np.array([[10,5],[20,30],[70,20],[50,10]], np.int32)
pts=pts.reshape((-1,1,2))
cv2.polylines(img,[pts], True, (0,0,255),1)
# 这里 reshape 的第一个参数为-1, 表明这一维的长度是根据后面的维度的计算出来的。
#添加文字
font=cv2.FONT_HERSHEY_SIMPLEX
cv2.putText(img,'OpenCV',(10,500), font, 4,(255,255,255),2)
winname = 'example'
cv2.namedWindow(winname)
cv2.imshow(winname, img)
cv2.waitKey(5000)
cv2.destroyWindow(winname)

8.图像平移

import cv2
import numpy as np
img = cv2.imread('img2.png')
# 构造移动矩阵H
# 在x轴方向移动多少距离,在y轴方向移动多少距离
H = np.float32([[1, 0, 50], [0, 1, 25]])
rows, cols = img.shape[:2]
print(img.shape)
print(rows, cols)

# 注意这里rows和cols需要反置,即先列后行
res = cv2.warpAffine(img, H, (2*cols, 2*rows))  
cv2.imshow('origin_picture', img)
cv2.waitKey(5000)
cv2.imshow('new_picture', res)
cv2.waitKey(5000)
cv2.destroyAllWindows()

9.图像缩放

import cv2
import numpy as np

img = cv2.imread('img2.png')
# 方法一:通过设置缩放比例,来对图像进行放大或缩小
res1 = cv2.resize(img, None, fx=2, fy=2, 
                  interpolation=cv2.INTER_CUBIC)
height, width = img.shape[:2]
# 方法二:直接设置图像的大小,不需要缩放因子
#cv2.INTER_NEAREST(最近邻插值)
#cv2.INTER_AREA (区域插值)
#cv2.INTER_CUBIC(三次样条插值)
#cv2.INTER_LANCZOS4(Lanczos插值)
res2 = cv2.resize(img, (int(0.8*width), int(0.8*height)),interpolation=cv2.INTER_LANCZOS4)
cv2.imshow('origin_picture', img)
#|cv2.imshow('res1', res1)
cv2.imshow('res2', res2)
cv2.waitKey(5000)
cv2.destroyAllWindows()

10.图像旋转

import cv2
import numpy as np
img=cv2.imread('img2.png',1)
rows,cols=img.shape[:2]
#参数1:旋转中心,参数2:旋转角度,参数3:缩放因子
#参数3正为逆时针,负值为正时针
M=cv2.getRotationMatrix2D((cols/2,rows/2),45,1,)
print(M)
#第三个参数是输出图像的尺寸中心
dst=cv2.warpAffine(img,M,(cols,rows))
#dst=cv2.warpAffine(img,M,(cols,rows),borderValue=(255,255,255))
while(1):
    cv2.imshow('img', img)
    cv2.imshow('img1',dst)
    #0xFF==27  ESC
    if cv2.waitKey(1)&0xFF==27:
        break
cv2.destroyAllWindows()

11.仿射变换

import cv2
import numpy as np
import matplotlib.pyplot as plt
#读取图片
src = cv2.imread('bird.png')
#获取图像大小
rows, cols = src.shape[:2]
#设置图像仿射变换矩阵
pos1 = np.float32([[50,50], [200,50], [50,200]])
pos2 = np.float32([[10,100], [200,50], [100,250]])
M = cv2.getAffineTransform(pos1, pos2)
print(M)
#图像仿射变换
result = cv2.warpAffine(src, M, (2*cols, 2*rows))
#显示图像
cv2.imshow("original", src)
cv2.imshow("result", result)
#等待显示
cv2.waitKey(5000)
cv2.destroyAllWindows()

12.透视变化

import cv2
import numpy as np
import matplotlib.pyplot as plt
#读取图片
src = cv2.imread('bird.png')
#获取图像大小
rows, cols = src.shape[:2]
#设置图像透视变换矩阵
pos1 = np.float32([[114, 82], [287, 156],
                   [8, 100], [143, 177]])
pos2 = np.float32([[0, 0], [188, 0], 
                   [0, 262], [188, 262]])
M = cv2.getPerspectiveTransform(pos1, pos2)
#图像透视变换
result = cv2.warpPerspective(src, M, (2*cols,2*rows))
#显示图像
cv2.imshow("original", src)
cv2.imshow("result", result)
#等待显示
cv2.waitKey(5000)
cv2.destroyAllWindows()

13.文档校正

#encoding:utf-8
import cv2
import numpy as np
import matplotlib.pyplot as plt
#读取图片
src = cv2.imread('paper.png')
#获取图像大小
rows, cols = src.shape[:2]
#将源图像高斯模糊
img = cv2.GaussianBlur(src, (3,3), 0)
#进行灰度化处理
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
#边缘检测(检测出图像的边缘信息)
edges = cv2.Canny(gray,50,250,apertureSize = 3)
cv2.imwrite("canny.jpg", edges)
cv2.imshow("canny", edges)
#通过霍夫变换得到A4纸边缘
lines = cv2.HoughLinesP(edges,1,np.pi/180,50,minLineLength=90,maxLineGap=10)
print(lines)
#下面输出的四个点分别为四个顶点
for x1,y1,x2,y2 in lines[0]:
    print(x1,y1)
    print(x2,y2)
for x3,y3,x4,y4 in lines[1]:
    print(x3,y3)
    print(x4,y4)
#绘制边缘
for x1,y1,x2,y2 in lines[0]:
    cv2.line(gray, (x1,y1), (x2,y2), (0,0,255), 1)
#根据四个顶点设置图像透视变换矩阵
pos1 = np.float32([[114, 82], [287, 156], [8, 322], [216, 333]]) 
pos2 = np.float32([[0, 0], [188, 0], [0, 262], [188, 262]])
M = cv2.getPerspectiveTransform(pos1, pos2)
# pos1 = np.float32([[114, 82], [287, 156], [8, 322]])
# pos2 = np.float32([[0, 0], [188, 0], [0, 262]])
# M = cv2.getAffineTransform(pos1,pos2)
print(M)
#图像仿射变换
#result = cv2.warpAffine(src, M, (2*cols, 2*rows))
#图像透视变换
result = cv2.warpPerspective(src, M, (190, 272))
#显示图像
cv2.imshow("original", src)
cv2.imshow("result", result)
cv2.imshow("gray", gray)
#等待显示
cv2.waitKey(5000)
cv2.destroyAllWindows()

14.图像几何变换

#encoding:utf-8
import cv2  
import numpy as np
import matplotlib.pyplot as plt
#读取图片
img = cv2.imread('test2.png')
image = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
#图像平移矩阵
M = np.float32([[1, 0, 80], [0, 1, 30]])
rows, cols = image.shape[:2]
img1 = cv2.warpAffine(image, M, (cols, rows))
#图像缩小
img2 = cv2.resize(image, (200,100))
#图像放大
img3 = cv2.resize(image, None, fx=1.1, fy=1.1)
#绕图像的中心旋转
#源图像的高、宽 以及通道数
rows, cols, channel = image.shape
#函数参数:旋转中心 旋转度数 scale
M = cv2.getRotationMatrix2D((cols/2, rows/2), 30, 1) 
#函数参数:原始图像 旋转参数 元素图像宽高
img4 = cv2.warpAffine(image, M, (cols, rows))
#图像翻转
img5 = cv2.flip(image, 0)   #参数=0以X轴为对称轴翻转 
img6 = cv2.flip(image, 1)   #参数>0以Y轴为对称轴翻转
#图像的仿射
pts1 = np.float32([[50,50],[200,50],[50,200]])
pts2 = np.float32([[10,100],[200,50],[100,250]])
M = cv2.getAffineTransform(pts1,pts2)
img7 = cv2.warpAffine(image, M, (rows,cols))
#图像的透射
pts1 = np.float32([[56,65],[238,52],[28,237],[239,240]])
pts2 = np.float32([[0,0],[200,0],[0,200],[200,200]])
M = cv2.getPerspectiveTransform(pts1,pts2)
img8 = cv2.warpPerspective(image,M,(200,200))
#循环显示图形
titles = [ 'source', 'shift', 'reduction', 'enlarge', 'rotation', 'flipX', 'flipY', 'affine', 'transmission']  
images = [image, img1, img2, img3, img4, img5, img6, img7, img8]  
for i in range(9):  
    plt.subplot(3, 3, i+1), plt.imshow(images[i], 'gray')  
    plt.title(titles[i])  
    plt.xticks([]),plt.yticks([])  
plt.show()  

2.第二节:频域操作

1.方框滤波

import cv2
import numpy as np
img = cv2.imread('girl2.png',cv2.IMREAD_UNCHANGED)
r = cv2.boxFilter(img, -1 , (7,7) , normalize = 1)
d = cv2.boxFilter(img, -1 , (3,3) , normalize = 0)
cv2.namedWindow('img',cv2.WINDOW_AUTOSIZE)
cv2.namedWindow('r',cv2.WINDOW_AUTOSIZE)
cv2.namedWindow('d',cv2.WINDOW_AUTOSIZE)
cv2.imshow('img',img)
cv2.imshow('r',r)
cv2.imshow('d',d)
cv2.waitKey(5000)
cv2.destroyAllWindows()

2.均值模糊

import cv2
import numpy as np
from matplotlib import pyplot as plt
img = cv2.imread('image/opencv.png')
cv2.imshow('img',img)
cv2.waitKey(5000)
cv2.destroyAllWindows()
img = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
blur = cv2.blur(img,(30,30 ))
plt.subplot(121),plt.imshow(img),plt.title('Original')
plt.subplot(122),plt.imshow(blur),plt.title('Blurred')
plt.xticks([]), plt.yticks([])
plt.show()

2.(增)图像卷积,图像滤波

import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt
img = cv.imread('./image/opencv.png')
kernel = np.ones((10,10),np.float32)/100
dst = cv.filter2D(img,-1,kernel)
plt.subplot(121),plt.imshow(img),plt.title('Original')
plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(dst),plt.title('Averaging')
plt.xticks([]), plt.yticks([])
plt.show()

3.高斯模糊

import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
img = cv.imread('image/median.png')
img = cv.cvtColor(img,cv.COLOR_BGR2RGB)
blur = cv.GaussianBlur(img,(7,7),7)
plt.subplot(121),plt.imshow(img),plt.title('Original')
plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(blur),plt.title('Blurred')
plt.xticks([]), plt.yticks([])
plt.show()

4.中值模糊

import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
img = cv.imread('image/median.png')
median = cv.medianBlur(img,3)
plt.subplot(121),plt.imshow(img),plt.title('Original')
plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(median),plt.title('median')
plt.xticks([]), plt.yticks([])
plt.show()

5.双边滤波

简单起见,可以令2个sigma的值相等;

如果他们很小(小于10),那么滤波器几乎没有什么效果;
如果他们很大(大于150),那么滤波器的效果会很强,使图像显得非常卡通化;
关于参数d:

过大的滤波器(d>5)执行效率低。
对于实时应用,建议取d=5;
对于需要过滤严重噪声的离线应用,可取d=9;
d>0时,由d指定邻域直径;
d<=0时,d会自动由sigmaSpace的值确定,且d与sigmaSpace成正比;

import cv2
from matplotlib import pyplot as plt
img = cv2.imread('image/bilateral.png')
img = cv2.cvtColor(img,cv.COLOR_BGR2RGB)
blur = cv2.bilateralFilter(img,-1,15,10)#模板大小15,滤波10次
plt.subplot(121),plt.imshow(img),plt.title('Original')
plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(blur),plt.title('Blurred')
plt.xticks([]), plt.yticks([])
plt.show()

6.图像锐化

import cv2 as cv
import numpy as np
 
def custom_blur_demo(image):
    kernel = np.array([[0, -1, 0], [-1, 5, -1], [0, -1, 0]], np.float32) #锐化
    dst = cv.filter2D(image, -1, kernel=kernel)
    cv.imshow("custom_blur_demo", dst)
src = cv.imread("./image/sharpen.png")
cv.namedWindow("input image", cv.WINDOW_AUTOSIZE)
cv.imshow("input image", src)
custom_blur_demo(src)
cv.waitKey(5000)
cv.destroyAllWindows()

7.直方图均衡化

#导入opencv
import cv2
#直接读为灰度图像
img = cv2.imread('./image/dark.png',0)
cv2.imshow("dark",img)
cv2.waitKey(5000)
#调用cv2.equalizeHist函数进行直方图均衡化
img_equal = cv2.equalizeHist(img)
cv2.imshow("img_equal",img_equal)
cv2.waitKey(5000)
cv2.destroyAllWindows()
#导入opencv
import cv2
#直接读为灰度图像
img = cv2.imread('./image/dark.png',0)
cv2.imshow("dark",img)
cv2.waitKey(5000)
#调用cv2.createCLAHE函数进行局部直方图均衡化
clahe = cv2.createCLAHE(clipLimit=2,tileGridSize=(30,30))
cl1 = clahe.apply(img)

cv2.imshow("img_equal",cl1)
cv2.waitKey(5000)
cv2.destroyAllWindows()
import cv2
import numpy as np
img = cv2.imread("./image/dark1.jpg")
cv2.imshow("src", img)
# 彩色图像均衡化,需要分解通道 对每一个通道均衡化
(b, g, r) = cv2.split(img)
bH = cv2.equalizeHist(b)
gH = cv2.equalizeHist(g)
rH = cv2.equalizeHist(r)
# 合并每一个通道
result = cv2.merge((bH, gH, rH))
cv2.imshow("dst", result)
cv2.waitKey(0)
cv2.destroyAllWindows()

8.Gamma变化

import cv2
import numpy as np
img=cv2.imread('./image/dark1.jpg')
def adjust_gamma(image, gamma=1.0):
    invGamma = 1.0/gamma
    table = []
    for i in range(256):
        table.append(((i / 255.0) ** invGamma) * 255)
    table = np.array(table).astype("uint8")
    print(table)
    return cv2.LUT(image, table)

img_gamma = adjust_gamma(img, 0.8)
#print(img_gamma)
cv2.imshow("img",img)
cv2.imshow("img_gamma",img_gamma)

cv2.waitKey(5000)
cv2.destroyAllWindows()

9.形态学操作

腐蚀
import cv2
import numpy as np 
import matplotlib.pyplot as plt
img = cv2.imread('./image/morphology.png')
img = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
kernel = np.ones((3,3),np.uint8)
erosion = cv2.erode(img,kernel,iterations = 1)
plt.subplot(121),plt.imshow(img),plt.title('Original')
plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(erosion),plt.title('erosion')
plt.xticks([]), plt.yticks([])
plt.show()
#kernel = np.ones((5,5),np.uint8)
#kernel = cv2.getStructuringElement(cv2.MORPH_CROSS, (7,7))
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (7,7))
#kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (7,7))
print(kernel)
膨胀
import cv2 
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread('./image/morphology.png')
img = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
#kernel = np.ones((3,),np.uint8)
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (7,7))
dilation = cv2.dilate(img,kernel,iterations = 5)
kernel1 = np.ones((7,7),np.uint8)
opening = cv2.morphologyEx(dilation,cv2.MORPH_OPEN,kernel1)
plt.subplot(121),plt.imshow(opening),plt.title('opening')
plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(dilation),plt.title('dilation')
plt.xticks([]), plt.yticks([])
plt.show()
开运算:

侵蚀然后扩张的另一个名称,它对于消除噪音很有用

import cv2
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread('./image/open.png')
img = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
#kernel = np.ones((5,5),np.uint8)
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (9,9))
opening = cv2.morphologyEx(img,cv2.MORPH_OPEN,kernel)
plt.subplot(121),plt.imshow(img),plt.title('Original')
plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(opening),plt.title('opening')
plt.xticks([]), plt.yticks([])
plt.show()
闭运算:

闭运算与开运算相反,先扩张然后再侵蚀。在关闭前景对象内部的小孔或对象上的小黑点时很有 用。

import cv2 as cv
import numpy as np
img = cv.imread('./image/close.png')
img = cv.cvtColor(img,cv.COLOR_BGR2RGB)
#kernel = np.ones((5,5),np.uint8)
kernel = np.ones((7,7),np.uint8)
closing = cv.morphologyEx(img,cv.MORPH_CLOSE,kernel)
plt.subplot(121),plt.imshow(img),plt.title('Original')
plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(closing),plt.title('closing')
plt.xticks([]), plt.yticks([])
plt.show()
形态学梯度
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt
img = cv.imread('./image/morphology.png')
img = cv.cvtColor(img,cv.COLOR_BGR2RGB)
kernel = np.ones((3,3),np.uint8)
gradient = cv.morphologyEx(img,cv.MORPH_GRADIENT,kernel)
plt.subplot(121),plt.imshow(img),plt.title('Original')
plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(gradient),plt.title('gradient')
plt.xticks([]), plt.yticks([])
plt.show()
顶帽:

它是输入图像和图像开运算之差。下面的示例针对9x9内核完成。

import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt
img = cv.imread('./image/morphology.png')
img = cv.cvtColor(img,cv.COLOR_BGR2RGB)
kernel = np.ones((9,9),np.uint8)
tophat = cv.morphologyEx(img,cv.MORPH_TOPHAT,kernel)
plt.subplot(121),plt.imshow(img),plt.title('Original')
plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(tophat),plt.title('tophat')
plt.xticks([]), plt.yticks([])
plt.show()
黑帽:

这是输入图像和图像闭运算之差。

import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt
img = cv.imread('./image/morphology.png')
img = cv.cvtColor(img,cv.COLOR_BGR2RGB)
kernel = np.ones((9,9),np.uint8)
tophat = cv.morphologyEx(img,cv.MORPH_BLACKHAT,kernel)
plt.subplot(121),plt.imshow(img),plt.title('Original')
plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(tophat),plt.title('tophat')
plt.xticks([]), plt.yticks([])
plt.show()

8.结构元素

cv.getStructuringElement(cv.MORPH_RECT,(5,5))
a = [[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]]
print(a)
# 椭圆内核
cv.getStructuringElement(cv.MORPH_ELLIPSE,(5,5))

三、图像分割

1.固定阈值

#加载opencv和matplotlib
import cv2
import matplotlib.pyplot as plt
# 灰度图读入
img = cv2.imread('./image/thresh.png', 0)
threshold = 127
# 阈值分割
ret, th = cv2.threshold(img, threshold, 255, cv2.THRESH_BINARY)
print(ret)
cv2.imshow('thresh', th)
cv2.waitKey(0)
cv2.destroyAllWindows()

2.固定阈值不同方法比较

#导入第三方包
import cv2
from matplotlib import pyplot as plt
#opencv读取图像 
img = cv2.imread('./image/person.png',0)
#5种阈值法图像分割
ret, thresh1 = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY)
ret, thresh2 = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY_INV)
ret, thresh3 = cv2.threshold(img, 127, 255,cv2.THRESH_TRUNC)
ret, thresh4 = cv2.threshold(img, 127, 255, cv2.THRESH_TOZERO)
ret, thresh5 = cv2.threshold(img, 127, 255, cv2.THRESH_TOZERO_INV)

images = [img, thresh1, thresh2, thresh3, thresh4, thresh5]
#使用for循环进行遍历,matplotlib进行显示
for i in range(6):
    plt.subplot(2,3, i+1)
    plt.imshow(images[i],cmap='gray')
    plt.xticks([])
    plt.yticks([])

plt.suptitle('fixed threshold')
plt.show()

3.自适应阈值与固定阈值对比

#自适应阈值与固定阈值对比
import cv2
import matplotlib.pyplot as plt
img = cv2.imread('./image/paper2.png', 0)

# 固定阈值
ret, th1 = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY)
# 自适应阈值
th2 = cv2.adaptiveThreshold(
    img, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY,11, 4)
th3 = cv2.adaptiveThreshold(
    img, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 11, 4)
#全局阈值,均值自适应,高斯加权自适应对比
titles = ['Original', 'Global(v = 127)', 'Adaptive Mean', 'Adaptive Gaussian']
images = [img, th1, th2, th3]
for i in range(4):
    plt.subplot(2, 2, i + 1), plt.imshow(images[i], 'gray')
    plt.title(titles[i], fontsize=8)
    plt.xticks([]), plt.yticks([])
plt.show()

4.迭代法

import tensorflow as tf
import cv2
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.cm as cm

def best_thresh(img):
    img_array = np.array(img).astype(np.float32)#转化成数组
    I=img_array
    zmax=np.max(I)
    zmin=np.min(I)
    tk=(zmax+zmin)/2#设置初始阈值
    #根据阈值将图像进行分割为前景和背景,分别求出两者的平均灰度zo和zb
    b=1
    m,n=I.shape;
    while b==0:
        ifg=0
        ibg=0
        fnum=0
        bnum=0
        for i in range(1,m):
             for j in range(1,n):
                tmp=I(i,j)
                if tmp>=tk:
                    ifg=ifg+1
                    fnum=fnum+int(tmp)#前景像素的个数以及像素值的总和
                else:
                    ibg=ibg+1
                    bnum=bnum+int(tmp)#背景像素的个数以及像素值的总和
        #计算前景和背景的平均值
        zo=int(fnum/ifg)
        zb=int(bnum/ibg)
        if tk==int((zo+zb)/2):
            b=0
        else:
            tk=int((zo+zb)/2)
    return tk

img = cv2.imread("./image/bird.png")
img = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
gray = cv2.cvtColor(img,cv2.COLOR_RGB2GRAY)
img = cv2.resize(gray,(200,200))#大小
yvzhi=best_thresh(img)
ret1, th1 = cv2.threshold(img, yvzhi, 255, cv2.THRESH_BINARY)
print(ret1)
plt.subplot(2,1,1)
plt.imshow(img)
plt.subplot(2,1,2)
plt.imshow(th1,cmap=cm.gray)
plt.show()

5.otsu大津法

import cv2
from matplotlib import pyplot as plt
img = cv2.imread('./image/noisy.png', 0)
# 固定阈值法
ret1, th1 = cv2.threshold(img, 100, 255, cv2.THRESH_BINARY)
# Otsu阈值法
ret2, th2 = cv2.threshold(img, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)

# 先进行高斯滤波,再使用Otsu阈值法
blur = cv2.GaussianBlur(img, (5, 5), 0)
ret3, th3 = cv2.threshold(blur, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
images = [img, 0, th1, img, 0, th2, blur, 0, th3]
titles = ['Original', 'Histogram', 'Global(v=100)',
         'Original', 'Histogram', "Otsu's",
         'Gaussian filtered Image', 'Histogram', "Otsu's"]

for i in range(3):
    # 绘制原图
    plt.subplot(3, 3, i * 3 + 1)
    plt.imshow(images[i * 3], 'gray')
    plt.title(titles[i * 3], fontsize=8)
    plt.xticks([]), plt.yticks([])
    
    # 绘制直方图plt.hist, ravel函数将数组降成一维
    plt.subplot(3, 3, i * 3 + 2)
    plt.hist(images[i * 3].ravel(), 256)
    plt.title(titles[i * 3 + 1], fontsize=8)
    plt.xticks([]), plt.yticks([])
    
    # 绘制阈值图
    plt.subplot(3, 3, i * 3 + 3)
    plt.imshow(images[i * 3 + 2], 'gray')
    plt.title(titles[i * 3 + 2], fontsize=8)
    plt.xticks([]), plt.yticks([])
plt.show()
#Otsu源码
import numpy as np
 
def OTSU_enhance(img_gray, th_begin=0, th_end=256, th_step=1):
    #"must input a gary_img"
    assert img_gray.ndim == 2
 
    max_g = 0
    suitable_th = 0
    for threshold in range(th_begin, th_end, th_step):
        bin_img = img_gray > threshold
        bin_img_inv = img_gray <= threshold
        fore_pix = np.sum(bin_img)
        back_pix = np.sum(bin_img_inv)
        if 0 == fore_pix:
            break
        if 0 == back_pix:
            continue
 
        w0 = float(fore_pix) / img_gray.size
        u0 = float(np.sum(img_gray * bin_img)) / fore_pix
        w1 = float(back_pix) / img_gray.size
        u1 = float(np.sum(img_gray * bin_img_inv)) / back_pix
        # intra-class variance
        g = w0 * w1 * (u0 - u1) * (u0 - u1)
        if g > max_g:
            max_g = g
            suitable_th = threshold
    return suitable_th
img = cv2.imread('./image/noisy.png', 0)
thresh = OTSU_enhance(img)
ret1, th1 = cv2.threshold(img, thresh, 255, cv2.THRESH_BINARY)
ret2, th2 = cv2.threshold(img, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)
a = plt.imshow(th1,cmap=cm.gray)
plt.show(a)
b = plt.imshow(th2,cmap=cm.gray)
plt.show(b)

6.sobel代码

import numpy as np
import cv2
from matplotlib import pyplot as plt
img = cv2.imread('image/girl2.png',0)
sobelx = cv2.Sobel(img,cv2.CV_64F,1,0,ksize=5)
sobely = cv2.Sobel(img,cv2.CV_64F,0,1,ksize=5)

plt.subplot(1,3,1),plt.imshow(img,cmap = 'gray')
plt.title('Original'), plt.xticks([]), plt.yticks([])
plt.subplot(1,3,2),plt.imshow(sobelx,cmap = 'gray')
plt.title('Sobel X'), plt.xticks([]), plt.yticks([])
plt.subplot(1,3,3),plt.imshow(sobely,cmap = 'gray')
plt.title('Sobel Y'), plt.xticks([]), plt.yticks([])
plt.show()

7.Canny边缘检测算法

#加载opencv和numpy
import cv2
import numpy as np
#以灰度图形式读入图像
img = cv2.imread('image/canny.png')
v1 = cv2.Canny(img, 80, 150,(3,3))
v2 = cv2.Canny(img, 50, 100,(5,5))
#np.vstack():在竖直方向上堆叠
#np.hstack():在水平方向上平铺堆叠
ret = np.hstack((v1, v2))
cv2.imshow('img', ret)
cv2.waitKey(0)
cv2.destroyAllWindows()

8.连通区域分析

import cv2
import numpy as np

# 4邻域的连通域和 8邻域的连通域
# [row, col]
NEIGHBOR_HOODS_4 = True
OFFSETS_4 = [[0, -1], [-1, 0], [0, 0], [1, 0], [0, 1]]

NEIGHBOR_HOODS_8 = False
OFFSETS_8 = [[-1, -1], [0, -1], [1, -1],
             [-1,  0], [0,  0], [1,  0],
             [-1,  1], [0,  1], [1,  1]]
#第二遍扫描
def reorganize(binary_img: np.array):
    index_map = []
    points = []
    index = -1
    rows, cols = binary_img.shape
    for row in range(rows):
        for col in range(cols):
            var = binary_img[row][col]
            if var < 0.5:
                continue
            if var in index_map:
                index = index_map.index(var)
                num = index + 1
            else:
                index = len(index_map)
                num = index + 1
                index_map.append(var)
                points.append([])
            binary_img[row][col] = num
            points[index].append([row, col])
    #print(binary_img)
    #print(points)
    return binary_img, points

#四领域或八领域判断
def neighbor_value(binary_img: np.array, offsets, reverse=False):
    rows, cols = binary_img.shape
    label_idx = 0
    rows_ = [0, rows, 1] if reverse == False else [rows-1, -1, -1]
    cols_ = [0, cols, 1] if reverse == False else [cols-1, -1, -1]
    for row in range(rows_[0], rows_[1], rows_[2]):
        for col in range(cols_[0], cols_[1], cols_[2]):
            label = 256
            if binary_img[row][col] < 0.5:
                continue
            for offset in offsets:
                neighbor_row = min(max(0, row+offset[0]), rows-1)
                neighbor_col = min(max(0, col+offset[1]), cols-1)
                neighbor_val = binary_img[neighbor_row, neighbor_col]
                if neighbor_val < 0.5:
                    continue
                label = neighbor_val if neighbor_val < label else label
            if label == 255:
                label_idx += 1
                label = label_idx
            binary_img[row][col] = label
    print('第一遍扫描:',binary_img)
    print('开始第二遍...')
    return binary_img

# binary_img: bg-0, object-255; int
#第一遍扫描
def Two_Pass(binary_img: np.array, neighbor_hoods):
    if neighbor_hoods == NEIGHBOR_HOODS_4:
        offsets = OFFSETS_4
    elif neighbor_hoods == NEIGHBOR_HOODS_8:
        offsets = OFFSETS_8
    else:
        raise ValueError

    binary_img = neighbor_value(binary_img, offsets, False)

    return binary_img

if __name__ == "__main__":
    #创建四行七列的矩阵
    binary_img = np.zeros((4, 7), dtype=np.int16)
    #指定点设置为255
    index = [[0, 2], [0, 5],
            [1, 0], [1, 1], [1, 2], [1, 4], [1, 5], [1, 6],
            [2, 2], [2, 5],
            [3, 1], [3, 2], [3, 4],[3,5], [3, 6]]
    for i in index:
        binary_img[i[0], i[1]] = np.int16(255)

    print("原始二值图像")
    print(binary_img)

    #print("Two_Pass")
    #调用Two Pass算法,计算第一遍扫面的结果
    binary_img = Two_Pass(binary_img, NEIGHBOR_HOODS_4)
    #print(binary_img)
    #计算第一遍扫面的结果
    binary_img, points = reorganize(binary_img)
    print(binary_img)
    #print(points)

9.区域生长算法

# -*- coding:utf-8 -*-
import cv2
import numpy as np

####################################################################################



#######################################################################################
class Point(object):
    def __init__(self , x , y):
        self.x = x
        self.y = y
    def getX(self):
        return self.x
    def getY(self):
        return self.y
connects = [ Point(-1, -1), Point(0, -1), Point(1, -1), Point(1, 0),
            Point(1, 1), Point(0, 1), Point(-1, 1), Point(-1, 0)]
#####################################################################################
#计算两个点间的欧式距离
def get_dist(seed_location1,seed_location2):
    l1 = im[seed_location1.x , seed_location1.y]
    l2 = im[seed_location2.x , seed_location2.y]
    count = np.sqrt(np.sum(np.square(l1-l2)))
    return count

#import Image
im = cv2.imread('image/222.jpg')
cv2.imshow('src' , im)
cv2.waitKey(0)
cv2.destroyAllWindows()
im_shape = im.shape
height = im_shape[0]
width = im_shape[1]

print( 'the shape of image :', im_shape)

#标记,判断种子是否已经生长
img_mark = np.zeros([height , width])
cv2.imshow('img_mark' , img_mark)
cv2.waitKey(0)
cv2.destroyAllWindows()

# 建立空的图像数组,作为一类
img_re = im.copy()
for i in range(height):
    for j in range(width):
        img_re[i, j][0] = 0
        img_re[i, j][1] = 0
        img_re[i, j][2] = 0
cv2.imshow('img_re' , img_re)
cv2.waitKey(0)
cv2.destroyAllWindows()
#取一点作为种子点
seed_list = []
seed_list.append(Point(15, 15))
T = 7#阈值
class_k = 1#类别
#生长一个类
while (len(seed_list) > 0):
    seed_tmp = seed_list[0]
    #将以生长的点从一个类的种子点列表中删除
    seed_list.pop(0)


    img_mark[seed_tmp.x, seed_tmp.y] = class_k

    # 遍历8邻域
    for i in range(8):
        tmpX = seed_tmp.x + connects[i].x
        tmpY = seed_tmp.y + connects[i].y

        if (tmpX < 0 or tmpY < 0 or tmpX >= height or tmpY >= width):
            continue
        dist = get_dist(seed_tmp, Point(tmpX, tmpY))
        #在种子集合中满足条件的点进行生长
        if (dist < T and img_mark[tmpX, tmpY] == 0):
            img_re[tmpX, tmpY][0] = im[tmpX, tmpY][0]
            img_re[tmpX, tmpY][1] = im[tmpX, tmpY][1]
            img_re[tmpX, tmpY][2] = im[tmpX, tmpY][2]
            img_mark[tmpX, tmpY] = class_k
            seed_list.append(Point(tmpX, tmpY))


########################################################################################

#输出图像
cv2.imshow('OUTIMAGE' , img_re)
cv2.waitKey(0)
cv2.destroyAllWindows()

10.分水岭算法

# import cv2
"""
完成分水岭算法步骤:
1、加载原始图像
2、阈值分割,将图像分割为黑白两个部分
3、对图像进行开运算,即先腐蚀在膨胀
4、对开运算的结果再进行 膨胀,得到大部分是背景的区域
5、通过距离变换 Distance Transform 获取前景区域
6、背景区域sure_bg 和前景区域sure_fg相减,得到即有前景又有背景的重合区域
7、连通区域处理
8、最后使用分水岭算法
"""

import cv2
import numpy as np


# Step1. 加载图像
img = cv2.imread('image/yezi.jpg')
cv2.imshow("img", img)
cv2.waitKey(0)
cv2.destroyAllWindows()
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# Step2.阈值分割,将图像分为黑白两部分
ret, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)
# cv2.imshow("thresh", thresh)

# Step3. 对图像进行“开运算”,先腐蚀再膨胀
kernel = np.ones((3, 3), np.uint8)
opening = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel, iterations=2)
# cv2.imshow("opening", opening)

# Step4. 对“开运算”的结果进行膨胀,得到大部分都是背景的区域
sure_bg = cv2.dilate(opening, kernel, iterations=3)
cv2.imshow("sure_bg", sure_bg)
cv2.waitKey(0)
cv2.destroyAllWindows()

# Step5.通过distanceTransform获取前景区域
dist_transform = cv2.distanceTransform(opening, cv2.DIST_L2, 5)  # DIST_L1 DIST_C只能 对应掩膜为3    DIST_L2 可以为3或者5
cv2.imshow("dist_transform", dist_transform)
cv2.waitKey(0)
cv2.destroyAllWindows()
print(dist_transform.max())
ret, sure_fg = cv2.threshold(dist_transform, 0.1 * dist_transform.max(), 255, 0)


# Step6. sure_bg与sure_fg相减,得到既有前景又有背景的重合区域   #此区域和轮廓区域的关系未知 
sure_fg = np.uint8(sure_fg)
unknow = cv2.subtract(sure_bg, sure_fg)
cv2.imshow("unknow", unknow)
cv2.waitKey(0)
cv2.destroyAllWindows()

# Step7. 连通区域处理
ret, markers = cv2.connectedComponents(sure_fg,connectivity=8) #对连通区域进行标号  序号为 0 - N-1 
#print(markers)
print(ret)
markers = markers + 1           #OpenCV 分水岭算法对物体做的标注必须都 大于1 ,背景为标号 为0  因此对所有markers 加1  变成了  1  -  N
#去掉属于背景区域的部分(即让其变为0,成为背景)
# 此语句的Python语法 类似于if ,“unknow==255” 返回的是图像矩阵的真值表。
markers[unknow==255] = 0   

# Step8.分水岭算法
markers = cv2.watershed(img, markers)  #分水岭算法后,所有轮廓的像素点被标注为  -1 
#print(markers)

img[markers == -1] = [0, 0, 255]   # 标注为-1 的像素点标 红
cv2.imshow("dst", img)
cv2.waitKey(0)
cv2.destroyAllWindows()

四、图像特征与目标检测

1.Hog特征

import cv2
import numpy as np
# 判断矩形i是否完全包含在矩形o中
def is_inside(o, i):
    ox, oy, ow, oh = o
    ix, iy, iw, ih = i
    return ox > ix and oy > iy and ox + ow < ix + iw and oy + oh < iy + ih
# 对人体绘制颜色框
def draw_person(image, person):
    x, y, w, h = person
    cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 255), 2)
img = cv2.imread("people.jpg")
hog = cv2.HOGDescriptor()  # 启动检测器对象
hog.setSVMDetector(cv2.HOGDescriptor_getDefaultPeopleDetector())  # 指定检测器类型为人体
found, w = hog.detectMultiScale(img,0.1,(1,1)) # 加载并检测图像
print(found)
print(w)

# 丢弃某些完全被其它矩形包含在内的矩形
found_filtered = []
for ri, r in enumerate(found):
    for qi, q in enumerate(found):
        if ri != qi and is_inside(r, q):
            break
    else:
        found_filtered.append(r)
        print(found_filtered)
# 对不包含在内的有效矩形进行颜色框定
for person in found_filtered:
    draw_person(img, person)
cv2.imshow("people detection", img)
cv2.waitKey(5000)
cv2.destroyAllWindows()

2.Harris角点检测

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

img = cv2.imread('harris2.png')
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
gray = np.float32(gray)
dst_block9_ksize19 = cv2.cornerHarris(gray, 9, 19, 0.04)
img1 = np.copy(img)
img1[dst_block9_ksize19 > 0.01 * dst_block9_ksize19.max()] = [0, 0, 255]

dst_block5_ksize19 = cv2.cornerHarris(gray, 5, 19, 0.04)
img2 = np.copy(img)
img2[dst_block5_ksize19 > 0.01 * dst_block5_ksize19.max()] = [0, 0, 255]

dst_block9_ksize5 = cv2.cornerHarris(gray, 9, 5, 0.04)
img3 = np.copy(img)
img3[dst_block9_ksize5 > 0.01 * dst_block9_ksize5.max()] = [0, 0, 255]

dst_block9_ksize31 = cv2.cornerHarris(gray, 9, 31, 0.04)
img4 = np.copy(img)
img4[dst_block9_ksize31 > 0.01 * dst_block9_ksize31.max()] = [0, 0, 255]

dst_block9_ksize19_k6 = cv2.cornerHarris(gray, 9, 19, 0.06)
img5 = np.copy(img)
img5[dst_block9_ksize19_k6 > 0.01 * dst_block9_ksize19_k6.max()] = [0, 0, 255]

dst_block9_ksize19_k6_1e_5 = cv2.cornerHarris(gray, 9, 19, 0.06)
img6 = np.copy(img)
img6[dst_block9_ksize19_k6_1e_5 > 0.00001 * dst_block9_ksize19_k6_1e_5.max()] = [0, 0, 255]

titles = ["Original", "block9_ksize19", "dst_block5_ksize19", "dst_block9_ksize5", "dst_block9_ksize31",
          "dst_block9_ksize19_k6", "dst_block9_ksize19_k6_1e_5"]
imgs = [img, img1, img2, img3, img4, img5, img6]
for i in range(len(titles)):
    plt.subplot(3, 3, i + 1), plt.imshow(imgs[i]), plt.title(titles[i])
    plt.xticks([]), plt.yticks([])
plt.show()
cv2.imshow('src',img)
cv2.imshow('dst',img5)
cv2.waitKey(5000)
cv2.destroyAllWindows()

3.Harris角点检测

# -*- coding: utf-8 -*-
import cv2
import numpy as np

filename = 'harris2.png'
img = cv2.imread(filename)
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
gray = np.float32(gray)

# 输入图像必须是 float32 ,最后一个参数在 0.04 到 0.06 之间
dst = cv2.cornerHarris(gray,2,3,0.06)

#结果进行膨胀,可有可无
dst = cv2.dilate(dst,None)
print(dst)
# 设定阈值,不同图像阈值不同
img[dst>0.01*dst.max()]=[0,0,255]
print(dst.max())
cv2.imshow('dst_img',img)
#cv2.imshow('dst',dst)
cv2.waitKey(5000)
cv2.destroyAllWindows()

4.SIFT算法

import cv2
import numpy as np

img = cv2.imread('harris2.png')
gray= cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
sift = cv2.xfeatures2d.SIFT_create()
kp = sift.detect(gray,None)#找到关键点
img=cv2.drawKeypoints(gray,kp,img)#绘制关键点
cv2.imshow('sp',img)
cv2.waitKey(0)
cv2.destroyAllWindows()

5.LBP特征

def LBP(src):
    '''
    :param src:灰度图像
    :return:
    '''
    height = src.shape[0]
    width = src.shape[1]
    dst = src.copy()
    lbp_value = np.zeros((1,8), dtype=np.uint8)
    #print(lbp_value)
    neighbours = np.zeros((1,8), dtype=np.uint8)
    #print(neighbours)
    for x in range(1, width-1):
        for y in range(1, height-1):
            neighbours[0, 0] = src[y - 1, x - 1]
            neighbours[0, 1] = src[y - 1, x]
            neighbours[0, 2] = src[y - 1, x + 1]
            neighbours[0, 3] = src[y, x - 1]
            neighbours[0, 4] = src[y, x + 1]
            neighbours[0, 5] = src[y + 1, x - 1]
            neighbours[0, 6] = src[y + 1, x]
            neighbours[0, 7] = src[y + 1, x + 1]
            center = src[y, x]
            for i in range(8):
                if neighbours[0, i] > center:
                    lbp_value[0, i] = 1
                else:
                    lbp_value[0, i] = 0

            lbp = lbp_value[0, 0] * 1 + lbp_value[0, 1] * 2 + lbp_value[0, 2] * 4 + lbp_value[0, 3] * 8 \
                + lbp_value[0, 4] * 16 + lbp_value[0, 5] * 32 + lbp_value[0, 6] * 64 + lbp_value[0, 7] * 128
            
            #print(lbp)
            dst[y, x] = lbp

    return dst
import cv2
import numpy as np
img = cv2.imread('people.jpg',0)
print(img.shape)
cv2.imshow('src',img)
cv2.waitKey(5000)
cv2.destroyAllWindows()
new_img = LBP(img)

cv2.imshow('dst',new_img)
cv2.waitKey(5000)
cv2.destroyAllWindows()

6.模板匹配

#模板匹配
import cv2
import numpy as np
def template_demo(tpl,target):

    methods = [cv2.TM_SQDIFF_NORMED, cv2.TM_CCORR_NORMED, cv2.TM_CCOEFF_NORMED]   #3种模板匹配方法
    th, tw = tpl.shape[:2]
    for md in methods:
        #print(md)
        result = cv2.matchTemplate(target, tpl, md)
        #print(result.shape)
        min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
        print(min_val, max_val, min_loc, max_loc)
        if md == cv2.TM_SQDIFF_NORMED:
            tl = min_loc
        else:
            tl = max_loc
        br = (tl[0]+tw, tl[1]+th)   #br是矩形右下角的点的坐标
        cv2.rectangle(target, tl, br, (0, 0, 255), 2)
        cv2.namedWindow("match-" + np.str(md), cv2.WINDOW_NORMAL)
        cv2.imshow("match-" + np.str(md), target)
        
tpl =cv2.imread("sample2.jpg")
print(tpl.shape)
target = cv2.imread("target1.jpg")
print(target.shape)
cv2.waitKey(5000)
cv2.destroyAllWindows()

cv2.namedWindow('template image', cv2.WINDOW_NORMAL)
cv2.imshow("template image", tpl)
cv2.namedWindow('target image', cv2.WINDOW_NORMAL)
cv2.imshow("target image", target)
template_demo(tpl,target)
cv2.waitKey(5000)
cv2.destroyAllWindows()

7.人脸检测方法1

import cv2

# 读入图像
img = cv2.imread("3.png")

# 加载人脸特征,该文件在 python安装目录\Lib\site-packages\cv2\data 下
face_cascade = cv2.CascadeClassifier(r'haarcascade_frontalface_default.xml')
# 将读取的图像转为COLOR_BGR2GRAY,减少计算强度
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# 检测出的人脸个数
faces = face_cascade.detectMultiScale(gray, scaleFactor = 1.15, minNeighbors = 4, minSize = (5, 5))

print("Face : {0}".format(len(faces)))
print(faces)
# 用矩形圈出人脸的位置
for(x, y, w, h) in faces:
    cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 2) 

cv2.namedWindow("Faces")
cv2.imshow("Faces", img)
cv2.waitKey(0)
cv2.destroyAllWindows()

8.人脸检测方法2

# -*- coding:utf-8 -*-
import cv2
import dlib
import numpy as np


predictor_model = 'shape_predictor_68_face_landmarks/shape_predictor_68_face_landmarks.dat'
detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor(predictor_model)

# cv2读取图像
test_film_path = "3.png"
img = cv2.imread(test_film_path)
# 取灰度
img_gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)

# 人脸数rects
rects = detector(img_gray, 0)
print(rects[0])
for i in range(len(rects)):
    landmarks = np.matrix([[p.x, p.y] for p in predictor(img,rects[i]).parts()])
    print(landmarks, type(landmarks))
    for idx, point in enumerate(landmarks):
        # 68点的坐标
        pos = (point[0, 0], point[0, 1])
        #print(idx+1, pos)

        # 利用cv2.circle给每个特征点画一个圈,共68个
        cv2.circle(img, pos, 3, color=(0, 255, 0))
        # 利用cv2.putText输出1-68
        font = cv2.FONT_HERSHEY_SIMPLEX
        cv2.putText(img, str(idx+1), pos, font, 0.5, (0, 0, 25 5), 1, cv2.LINE_AA)

#cv2.imwrite("result.png", img)
cv2.imshow("img", img)
cv2.waitKey(5000)
cv2.destroyAllWindows() 

五、运动目标识别

1.调用摄像头

import numpy as np
import cv2
cap = cv2.VideoCapture(0)
while(True):
    #获取一帧帧图像
    ret, frame = cap.read()
    #转化为灰度图
    #gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    cv2.imshow('frame',frame)
    #按下“q”键停止
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break
cap.release()
cv2.destroyAllWindows()

2.保存视屏

import cv2

#调用摄像头函数cv2.VideoCapture,参数0:系统摄像头
cap = cv2.VideoCapture(0)
#创建编码方式
#mp4:'X','V','I','D'avi:'M','J','P','G'或'P','I','M','1' flv:'F','L','V','1'
fourcc = cv2.VideoWriter_fourcc('F','L','V','1')

#创建VideoWriter对象
out = cv2.VideoWriter('output_1.flv',fourcc, 20.0, (640,480))
#创建循环结构进行连续读写
while(cap.isOpened()):
    ret, frame = cap.read()
    if ret==True:
        out.write(frame)
        cv2.imshow('frame',frame)
        if cv2.waitKey(1) & 0xFF == ord('q'):  
            break
    else:
        break
cap.release()
out.release()
cv2.destroyAllWindows()

3.修改视屏格式

import numpy as np
import cv2

cap = cv2.VideoCapture('output_1.flv')
fourcc = cv2.VideoWriter_fourcc('M','J','P','G')
fps = cap.get(cv2.CAP_PROP_FPS)
print(fps)

# 视频图像的宽度
frame_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
# 视频图像的长度
frame_height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
print(frame_width)
print(frame_height)
#创建VideoWriter对象
out = cv2.VideoWriter('output_1_new.mp4',fourcc, fps,(frame_width,frame_height))
while(True):
    ret, frame = cap.read()
    if ret==True:
        # 水平翻转
        frame = cv2.flip(frame,1)
        out.write(frame)
        cv2.imshow('frame',frame)
        if cv2.waitKey(25) & 0xff == ord('q'):
            break
    else:
        break
out.release()
cap.release()
cv2.destroyAllWindows()

4.帧差法

# 导入必要的软件包 
import cv2 
 
# 视频文件输入初始化 
filename = "move_detect.flv" 
camera = cv2.VideoCapture(filename) 
 
# 视频文件输出参数设置 
out_fps = 12.0  # 输出文件的帧率 
fourcc = cv2.VideoWriter_fourcc('M', 'P', '4', '2') 
out1 = cv2.VideoWriter('E:/video/v1.avi', fourcc, out_fps, (500, 400)) 
out2 = cv2.VideoWriter('E:/video/v2.avi', fourcc, out_fps, (500, 400)) 
 
# 初始化当前帧的前帧 
lastFrame = None 
 
# 遍历视频的每一帧 
while camera.isOpened(): 
 
    # 读取下一帧 
    (ret, frame) = camera.read() 
 
    # 如果不能抓取到一帧,说明我们到了视频的结尾 
    if not ret: 
        break 
 
    # 调整该帧的大小 
    frame = cv2.resize(frame, (500, 400), interpolation=cv2.INTER_CUBIC) 
 
    # 如果第一帧是None,对其进行初始化 
    if lastFrame is None: 
        lastFrame = frame 
        continue 
 
    # 计算当前帧和前帧的不同 
    frameDelta = cv2.absdiff(lastFrame, frame) 
 
    # 当前帧设置为下一帧的前帧 
    lastFrame = frame.copy() 
 
    # 结果转为灰度图 
    thresh = cv2.cvtColor(frameDelta, cv2.COLOR_BGR2GRAY) 
 
    # 图像二值化 
    thresh = cv2.threshold(thresh, 25, 255, cv2.THRESH_BINARY)[1] 
 
    ''' 
    #去除图像噪声,先腐蚀再膨胀(形态学开运算) 
    thresh=cv2.erode(thresh,None,iterations=1) 
    thresh = cv2.dilate(thresh, None, iterations=2) 
    ''' 
 
    # 阀值图像上的轮廓位置 
    binary, cnts, hierarchy = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) 
 
    # 遍历轮廓 
    for c in cnts: 
        # 忽略小轮廓,排除误差 
        if cv2.contourArea(c) < 300: 
            continue 
 
        # 计算轮廓的边界框,在当前帧中画出该框 
        (x, y, w, h) = cv2.boundingRect(c) 
        cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2) 
 
    # 显示当前帧 
    cv2.imshow("frame", frame) 
    cv2.imshow("frameDelta", frameDelta) 
    cv2.imshow("thresh", thresh) 
 
    # 保存视频 
    out1.write(frame) 
    out2.write(frameDelta) 
 
    # 如果q键被按下,跳出循环 
    if cv2.waitKey(20) & 0xFF == ord('q'): 
        break 
# 清理资源并关闭打开的窗口 
out1.release() 
out2.release() 
camera.release() 
cv2.destroyAllWindows()

5.光流法

import cv2 as cv
import numpy as np

es = cv.getStructuringElement(cv.MORPH_ELLIPSE, (10, 10))
kernel = cv.getStructuringElement(cv.MORPH_ELLIPSE, (3, 3))
cap = cv.VideoCapture("move_detect.flv")
frame1 = cap.read()[1]
prvs = cv.cvtColor(frame1, cv.COLOR_BGR2GRAY)
hsv = np.zeros_like(frame1)
hsv[..., 1] = 255

# 视频文件输出参数设置
out_fps = 12.0  # 输出文件的帧率
fourcc = cv.VideoWriter_fourcc('M', 'P', '4', '2')
sizes = (int(cap.get(cv.CAP_PROP_FRAME_WIDTH)), int(cap.get(cv.CAP_PROP_FRAME_HEIGHT)))
out1 = cv.VideoWriter('E:/video/v6.avi', fourcc, out_fps, sizes)
out2 = cv.VideoWriter('E:/video/v8.avi', fourcc, out_fps, sizes)

while True:
    (ret, frame2) = cap.read()
    next = cv.cvtColor(frame2, cv.COLOR_BGR2GRAY)
    flow = cv.calcOpticalFlowFarneback(prvs, next, None, 0.5, 3, 15, 3, 5, 1.2, 0)
    mag, ang = cv.cartToPolar(flow[..., 0], flow[..., 1])
    hsv[..., 0] = ang * 180 / np.pi / 2
    hsv[..., 2] = cv.normalize(mag, None, 0, 255, cv.NORM_MINMAX)

    bgr = cv.cvtColor(hsv, cv.COLOR_HSV2BGR)

    draw = cv.cvtColor(bgr, cv.COLOR_BGR2GRAY)
    draw = cv.morphologyEx(draw, cv.MORPH_OPEN, kernel)
    draw = cv.threshold(draw, 25, 255, cv.THRESH_BINARY)[1]

    image, contours, hierarchy = cv.findContours(draw.copy(), cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)

    for c in contours:
        if cv.contourArea(c) < 500:
            continue
        (x, y, w, h) = cv.boundingRect(c)
        cv.rectangle(frame2, (x, y), (x + w, y + h), (255, 255, 0), 2)

    cv.imshow('frame2', bgr)

    cv.imshow('draw', draw)
    cv.imshow('frame1', frame2)
    out1.write(bgr)
    out2.write(frame2)

    k = cv.waitKey(20) & 0xff
    if k == 27 or k == ord('q'):
        break
    elif k == ord('s'):
        cv.imwrite('opticalfb.png', frame2)
        cv.imwrite('opticalhsv.png', bgr)
    prvs = next

out1.release()
out2.release()
cap.release()
cv.destroyAllWindows()

6.背景减除法

import numpy as np
import cv2

# read the video
cap = cv2.VideoCapture('move_detect.flv')

# create the subtractor
fgbg = cv2.createBackgroundSubtractorMOG2(
    history=500, varThreshold=100, detectShadows=False)


def getPerson(image, opt=1):

    # get the front mask
    mask = fgbg.apply(frame)

    # eliminate the noise
    line = cv2.getStructuringElement(cv2.MORPH_RECT, (1, 5), (-1, -1))
    mask = cv2.morphologyEx(mask, cv2.MORPH_OPEN, line)
    cv2.imshow("mask", mask)

    # find the max area contours
    out, contours, hierarchy = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    for c in range(len(contours)):
        area = cv2.contourArea(contours[c])
        if area < 150:
            continue
        rect = cv2.minAreaRect(contours[c])
        cv2.ellipse(image, rect, (0, 255, 0), 2, 8)
        cv2.circle(image, (np.int32(rect[0][0]), np.int32(rect[0][1])), 2, (255, 0, 0), 2, 8, 0)
    return image, mask


while True:
    ret, frame = cap.read()
    cv2.imwrite("input.png", frame)
    cv2.imshow('input', frame)
    result, m_ = getPerson(frame)
    cv2.imshow('result', result)
    k = cv2.waitKey(20)&0xff
    if k == 27:
        cv2.imwrite("result.png", result)
        cv2.imwrite("mask.png", m_)

        break
cap.release()
cv2.destroyAllWindows()
  • 4
    点赞
  • 47
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值