写在前面的话,欢迎大家一起学习!
目录
安装
第一章 图像的基本操作
1.1图片读取
1.2视频的读取
1.3读取感兴趣的窗口
1.4图像通道
1.5边界填充
1.6改变图像大小以及图像混合
1.7图像融合
1.8利用mask掩膜抠出感兴趣的区域
1.9基本绘图操作
1.10 鼠标绘图
1.11几何操作
1.12亮度与对比度
1.13 轮廓检测以及多边形,凸包绘制
1.14动态绘制时钟
第二章 阈值与(滤波)平滑处理
第三章 图像形态学操作
3.1腐蚀操作
3.2膨胀操作
3.3开运算(即先腐蚀,再膨胀)
3.4闭运算(即先膨胀,再腐蚀)
3.5梯度运算(梯度=膨胀-腐蚀)
3.6顶帽(又称礼帽= 原始输入-开运算结果)
3.7黑帽(黑帽 = 闭运算-原始输入)
第四章 梯度计算--用于边缘检测(Canny,Sobel,Scharr)
第五章 图像金字塔
第六章轮廓检测
6.1轮廓检测
6.2利用 hsv追踪蓝色物体
第七章 图像直方图与傅里叶变换
7.1直方图
7.2傅里叶变换
第八章角点检测(Harris,shi_tomasi,sift)
第九章 模板匹配与KNN匹配
9.1模板匹配
9.2KNN匹配
9.3利用KNN匹配加透视变换实现全景图像拼接
第十章霍夫变换
第十一章 图像矫正
11.1仿射变换,透视变换
11.2基于傅里叶变换进行矫正
pip install opencv-python
pip install opencv-contrib-python
import cv2
import matplotlib.pyplot as plt
import numpy as np
img = cv2.imread('cat.jpg') # opencv默认读取BGR格式
print(img)
# 显示图像,可以创建多个窗口
cv2.imshow('Cat', img)
# 等待,0表示键盘任意键终止,如果为1000代表1000毫秒结束显示
cv2.waitKey(0)
#如果我们需要查看图像的维度,我们可以通过以下代码进行查看:
print(img.shape)
#如果我们需要读取灰度图片的话,我们可以采用以下的方式,添加一个参数即可:
img = cv2.imread('cat.jpg', cv2.IMREAD_GRAYSCALE)
#我们也可以通过以下方式将其保存起来。
print(img.size) #查看像素点的个数
cv2.destroyAllWindows()
import cv2
vc = cv2.VideoCapture('chaplin.mp4')
# 判断是否能够读取视频
if vc.isOpened():
open, frame = vc.read()
else:
open =False
while open:
ret, frame = vc.read()
if frame is None:
break
if ret == True:
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
cv2.imshow('result', gray)
if cv2.waitKey(100) & 0xFF == 27:
break
vc.release()
cv2.destroyAllWindows()
import cv2
img = cv2.imread('cat.jpg')
img2 = img[50:200, 100:400] # 切片读取感兴趣的区域
cv2.imshow('cat',img2)
cv2.waitKey(0)
cv2.destroyAllWindows()
import cv2
img = cv2.imread('cat1.jpg')
#我们可以通过以下的方式将其通道分开
b, g, r = cv2.split(img)
#也可以将其合并起来,记住,opencv里面颜色是bgr
img1 = cv2.merge((b, g, r))
cv2.imshow('cat_1', img1)
cop_img = img1.copy()
cop_img[:,:,0] = 0
cop_img[:,:,1] = 0
cv2.imshow('cat_only_r', cop_img)
cv2.waitKey(0)
cv2.destroyAllWindows()
#在卷积操作中经常需要边界填充padding
import cv2
import matplotlib.pyplot as plt
top_size, bottom_size, left_size, right_size = (50, 50, 50, 50)
img = cv2.imread('my.jpg')
replicate = cv2.copyMakeBorder(img, top_size, bottom_size, left_size, right_size, borderType=cv2.BORDER_REPLICATE)
reflect = cv2.copyMakeBorder(img, top_size, bottom_size, left_size, right_size,cv2.BORDER_REFLECT)
reflect101 = cv2.copyMakeBorder(img, top_size, bottom_size, left_size, right_size, cv2.BORDER_REFLECT_101)
wrap = cv2.copyMakeBorder(img, top_size, bottom_size, left_size, right_size, cv2.BORDER_WRAP)
constant = cv2.copyMakeBorder(img, top_size, bottom_size, left_size, right_size,cv2.BORDER_CONSTANT, value=0)
plt.subplot(231), plt.imshow(img), plt.title('ORIGINAL')
plt.subplot(232), plt.imshow(replicate), plt.title('REPLICATE')
plt.subplot(233), plt.imshow(reflect), plt.title('REFLECT')
plt.subplot(234), plt.imshow(reflect101), plt.title('REFLECT_101')
plt.subplot(235), plt.imshow(wrap), plt.title('WRAP')
plt.subplot(236), plt.imshow(constant), plt.title('CONSTANT')
plt.show()
import cv2
img_cat = cv2.imread('cat.jpg')
#对像素点直接进行加减。
img_cat_add = img_cat + 10
img_dog = cv2.imread('dog.jpg')
print('img_cat size',img_cat.shape)
print('img_dog size', img_dog.shape)
#改变图像大小
img_dog_resize = cv2.resize(img_dog, (550, 366))
print('img_dog_resize', img_dog_resize.shape)
#图像融合
res = cv2.addWeighted(img_cat, 0.3, img_dog_resize, 0.9, 0)
cv2.imshow('366*550',res)
cv2.waitKey(0)
cv2.destroyAllWindows()
import cv2
import numpy as np
# 1.按位操作
img1 = cv2.imread('cat.jpg')
img2 = cv2.imread('my.jpg')
# 把logo放在左上角,所以我们只关心这一块区域
rows, cols = img2.shape[:2] #shape[0] shape[1] shape[2] 高,长,通道
print(rows,cols)#132,132,3
roi = img1[50:182, 300:432] #在原图切出感兴趣区域roi,roi必须与mask掩膜大小相同
print(roi.shape)
cv2.imshow('roi', roi)
cv2.waitKey(0)
# 2.创建掩膜
img2gray = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)
ret, mask = cv2.threshold(img2gray, 10, 255, cv2.THRESH_BINARY)
mask_inv = cv2.bitwise_not(mask)
# 保留除logo外的背景
img1_bg = cv2.bitwise_and(roi, roi, mask=mask_inv)
dst = cv2.add(img1_bg, img2) # 进行融合
img1[50:182, 300:432] = dst # 融合后放在原图上
cv2.imshow('result', img1)
cv2.waitKey(0)
import cv2
import numpy as np
img = cv2.imread('my.jpg')
#圆心坐标,半径
x = 11
y = 11
r = 55
#创建掩膜
mask = np.zeros(img.shape[:2], dtype=np.uint8)
#mask[50:250, 130:320] = 255创建矩形区域
mask = cv2.circle(mask, (66, 66), r, (255, 255, 255), -1)
cv2.imshow("mask", mask)
#融合
result = cv2.add(img, np.zeros(np.shape(img), dtype=np.uint8), mask=mask)
res=np.hstack((img,result))
cv2.imshow("res", res)
cv2.waitKey()
cv2.destroyAllWindows()
import cv2
import numpy as np
# 创建一副黑色的图片
img = np.zeros((512, 512, 3), np.uint8)
# 1.画一条线宽为5的蓝色直线,参数2:起点,参数3:终点
cv2.line(img, (0, 0), (512, 512), (255, 0, 0), 5)
# 2.画一个绿色边框的矩形,参数2:左上角坐标,参数3:右下角坐标
cv2.rectangle(img, (384, 0), (510, 128), (0, 255, 0), 3)
# 3.画一个填充红色的圆,参数2:圆心坐标,参数3:半径
cv2.circle(img, (447, 63), 63, (0, 0, 255), -1)
# 4.在图中心画一个填充的半圆
cv2.ellipse(img, (256, 256), (100, 50), 0, 0, 180, (255, 0, 0), -1)
# 5.画一个闭合的四边形
# 定义四个顶点坐标
pts = np.array([[10, 5], [50, 10], [70, 20], [20, 30]], np.int32)
# 顶点个数:4,矩阵变成顶点数*1*2维(注意numpy中-1的用法)
pts = pts.reshape((-1, 1, 2))
cv2.polylines(img, [pts], True, (0, 255, 255))
#使用cv2.polylines()画多条直线
line1 = np.array([[100, 20], [300, 20]], np.int32).reshape((-1, 1, 2))
line2 = np.array([[100, 60], [300, 60]], np.int32).reshape((-1, 1, 2))
line3 = np.array([[100, 100], [300, 100]], np.int32).reshape((-1, 1, 2))
cv2.polylines(img, [line1, line2, line3], True, (0, 255, 255))
# 6.添加文字
font = cv2.FONT_HERSHEY_SIMPLEX
cv2.putText(img, 'zcz', (10, 500), font,
4, (255, 255, 255), 2, lineType=cv2.LINE_AA)
cv2.imshow('img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
import cv2
import numpy as np
start, end = (0, 0), (0, 0)
drawing = False
def mouse_event(event, x, y, flags, param):
global start, drawing, end, temp
# 鼠标按下,开始画图:记录下起点
if event == cv2.EVENT_LBUTTONDOWN:
drawing = True
start = (x, y)
# 实时移动的位置作为矩形终点(右下角点)
elif event == cv2.EVENT_MOUSEMOVE:
if drawing:
end = (x, y)
# 鼠标释放后,停止绘图
elif event == cv2.EVENT_LBUTTONUP:
drawing = False
cv2.rectangle(img, start, (x, y), (0, 255, 0), 2)
start = end = (0, 0)
img = np.zeros((512, 512, 3), np.uint8)
cv2.namedWindow('image')
cv2.setMouseCallback('image', mouse_event)
while(True):
# 下面这句话很关键,拷贝出原图,这样才可以实时画一个矩形
temp = np.copy(img)
if(drawing and end != (0, 0)):
cv2.rectangle(temp, start, end, (255, 0, 0), 2)
cv2.imshow('image', temp)
if cv2.waitKey(20) == 27:
break
import cv2
img = cv2.imread('my.jpg')
cv2.imshow('src', img)
cv2.waitKey(0)
# 1.按照指定的宽度、高度缩放图片
res = cv2.resize(img, (30, 30))
# 按照比例缩放,如x,y轴均放大一倍
res2 = cv2.resize(img, None, fx=2, fy=2, interpolation=cv2.INTER_LINEAR)
cv2.imshow('shrink', res), cv2.imshow('zoom', res2)
cv2.waitKey(0)
# 2.翻转图片,镜像操作
import numpy as np
# 参数2=0:垂直翻转(沿x轴),参数2>0: 水平翻转(沿y轴)
# 参数2<0: 水平垂直翻转
dst = cv2.flip(img, -1)
# np.hstack: 横向并排,对比显示
cv2.imshow('flip', np.hstack((img, dst))) # np.hstack: 横向并排,对比显示
cv2.waitKey(0)
# 3.平移图片
rows, cols = img.shape[:2]
# 定义平移矩阵,需要是numpy的float32类型
# x轴平移100,y轴平移50
M = np.float32([[1, 0, 100], [0, 1, 50]])
dst = cv2.warpAffine(img, M, (cols, rows))
cv2.imshow('shift', dst)
cv2.waitKey(0)
# 4.45°顺时针旋转图片并缩小一半
M = cv2.getRotationMatrix2D((cols / 2, rows / 2), -45, 0.5)
dst = cv2.warpAffine(img, M, (cols, rows))
cv2.imshow('rotation', dst)
cv2.waitKey(0)
cv2.destroyAllWindows()
import cv2
import numpy as np
def nothing(x):
'''
### 回调函数,暂时无用
'''
pass
img = cv2.imread('lena.jpg')
cv2.namedWindow('image')
# 创建两个滑块
cv2.createTrackbar('brightness', 'image', 0, 100, nothing)
cv2.createTrackbar('contrast', 'image', 100, 300, nothing)
temp = img.copy()
rows, cols = img.shape[:2]
while(True):
cv2.imshow('image', temp)
if cv2.waitKey(1) == 27:
break
# 得到两个滑块的值
brightness = cv2.getTrackbarPos('brightness', 'image')
contrast = cv2.getTrackbarPos('contrast', 'image') * 0.01
# 进行对比度和亮度调整
temp = np.uint8(np.clip(contrast * img + brightness, 0, 255))
import cv2
import numpy as np
# 多边形逼近
# 1.先找到轮廓
img = cv2.imread('unregular.jpg', 0)
_, thresh = cv2.threshold(img, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
image, contours, hierarchy = cv2.findContours(thresh, 3, 2)
cnt = contours[0]
# 2.进行多边形逼近,得到多边形的角点
approx = cv2.approxPolyDP(cnt, 3, True)
# 3.画出多边形
image = cv2.cvtColor(image, cv2.COLOR_GRAY2BGR)
cv2.polylines(image, [approx], True, (0, 255, 0), 2)
print(len(approx)) # 角点的个数
cv2.imshow('approxPloyDP', image)
cv2.waitKey(0)
# 凸包
# 1.先找到轮廓
img = cv2.imread('convex.jpg', 0)
_, thresh = cv2.threshold(img, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
image, contours, hierarchy = cv2.findContours(thresh, 3, 2)
cnt = contours[0]
# 2.寻找凸包,得到凸包的角点
hull = cv2.convexHull(cnt)
# 3.绘制凸包
image = cv2.cvtColor(image, cv2.COLOR_GRAY2BGR)
cv2.polylines(image, [hull], True, (0, 255, 0), 2)
cv2.imshow('convex hull', image)
cv2.waitKey(0)
# 轮廓是否是凸形的
print(cv2.isContourConvex(hull)) # True
# 关于returnPoints的理解:
print(hull[0]) # [[362 184]](坐标)
hull2 = cv2.convexHull(cnt, returnPoints=False)
print(hull2[0]) # [510](cnt中的索引)
print(cnt[510]) # [[362 184]]
# 点到轮廓距离(多边形测试)
dist = cv2.pointPolygonTest(cnt, (100, 100), True) # -3.53
print(dist)
import cv2
import math
import datetime
import numpy as np
margin = 5 # 上下左右边距
radius = 220 # 圆的半径
center = (center_x, center_y) = (225, 225) # 圆心
# 1. 新建一个画板并填充成白色
img = np.zeros((450, 450, 3), np.uint8)
img[:] = (255, 255, 255)
# 2. 画出圆盘
cv2.circle(img, center, radius, (0, 0, 0), thickness=5)
pt1 = []
# 3. 画出60条秒和分钟的刻线
for i in range(60):
# 最外部圆,计算A点
x1 = center_x+(radius-margin)*math.cos(i*6*np.pi/180.0)
y1 = center_y+(radius-margin)*math.sin(i*6*np.pi/180.0)
pt1.append((int(x1), int(y1)))
# 同心小圆,计算B点
x2 = center_x+(radius-15)*math.cos(i*6*np.pi/180.0)
y2 = center_y+(radius-15)*math.sin(i*6*np.pi/180.0)
cv2.line(img, pt1[i], (int(x2), int(y2)), (0, 0, 0), thickness=2)
# 4. 画出12条小时的刻线
for i in range(12):
# 12条小时刻线应该更长一点
x = center_x+(radius-25)*math.cos(i*30*np.pi/180.0)
y = center_y+(radius-25)*math.sin(i*30*np.pi/180.0)
# 这里用到了前面的pt1
cv2.line(img, pt1[i*5], (int(x), int(y)), (0, 0, 0), thickness=5)
# 到这里基本的表盘图就已经画出来了
while(1):
# 不断拷贝表盘图,才能更新绘制,不然会重叠在一起
temp = np.copy(img)
# 5. 获取系统时间,画出动态的时-分-秒三条刻线
now_time = datetime.datetime.now()
hour, minute, second = now_time.hour, now_time.minute, now_time.second
# 画秒刻线
# 参见博客,OpenCV中的角度是顺时针计算的,所以需要转换下
sec_angle = second*6+270 if second <= 15 else (second-15)*6
sec_x = center_x+(radius-margin)*math.cos(sec_angle*np.pi/180.0)
sec_y = center_y+(radius-margin)*math.sin(sec_angle*np.pi/180.0)
cv2.line(temp, center, (int(sec_x), int(sec_y)), (203, 222, 166), 2)
# 画分刻线
min_angle = minute*6+270 if minute <= 15 else (minute-15)*6
min_x = center_x+(radius-35)*math.cos(min_angle*np.pi/180.0)
min_y = center_y+(radius-35)*math.sin(min_angle*np.pi/180.0)
cv2.line(temp, center, (int(min_x), int(min_y)), (186, 199, 137), 8)
# 画时刻线
hour_angle = hour*30+270 if hour <= 3 else (hour-3)*30
hour_x = center_x+(radius-65)*math.cos(hour_angle*np.pi/180.0)
hour_y = center_y+(radius-65)*math.sin(hour_angle*np.pi/180.0)
cv2.line(temp, center, (int(hour_x), int(hour_y)), (169, 198, 26), 15)
# 6. 添加当前日期文字
font = cv2.FONT_HERSHEY_SIMPLEX
time_str = now_time.strftime("%d/%m/%Y")
cv2.putText(img, time_str, (135, 275), font, 1, (0, 0, 0), 2)
cv2.imshow('clocking', temp)
if cv2.waitKey(1) == 27: # 按下ESC键退出
break
#ret, dst = cv2.threshold(src, thresh, maxval, type)
#src: 输入图,只能输入单通道图像,通常来说为灰度图
#thresh: 阈值
#maxval: 当像素值超过了阈值(或者小于阈值,根据type来决定),所赋予的值
#type:二值化操作的类型,就是怎么处理阈值,包含以下5种类型:
#cv2.THRESH_BINARY 超过阈值部分取maxval(最大值),否则取0
#cv2.THRESH_BINARY_INV THRESH_BINARY的反转
#cv2.THRESH_TRUNC 大于阈值部分设为阈值,否则不变
#cv2.THRESH_TOZERO 大于阈值部分不改变,否则设为0
#cv2.THRESH_TOZERO_INV THRESH_TOZERO的反转
#cv2.THRESH_OTSU opencv自动选取阈值,适用于双峰图像
import cv2
import matplotlib.pyplot as plt
import numpy as np
img = cv2.imread('gradient.jpg')
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret1, thresh1 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_BINARY)
ret2, thresh2 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_BINARY_INV)
ret3, thresh3 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_TRUNC)
ret4, thresh4 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_TOZERO)
ret5, thresh5 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_TOZERO_INV)
ret6,thresh6 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_OTSU)
titles = ['Original Image', 'BINARY', 'BINARY_INV', 'TRUNC', 'TOZERO', 'TOZERO_INV','THRESH_OTSU']
images = [img, thresh1, thresh2, thresh3, thresh4, thresh5,thresh6]
for i in range(7):
plt.subplot(2, 4, i + 1), plt.imshow(images[i], 'gray')
plt.title(titles[i])
plt.xticks([]), plt.yticks([])
plt.show()
cv2.waitKey(0)
#平滑处理,起到平滑图像,虑去噪声的功能
img = cv2.imread('my.jpg')
#均值滤波(卷积核参数都是1)
blur = cv2.blur(img, (3, 3))
#方框滤波
#基本和均值一样,可以选择归一化,容易越界,如果归一化normalize等于True,那么和均值滤波一样,如果#normalize为False,那么大部分都将会发生越界的情况。
box = cv2.boxFilter(img,-1,(3,3), normalize=False)
#高斯滤波,更重视中值
aussian = cv2.GaussianBlur(img, (5, 5), 1)
#中值滤波
median = cv2.medianBlur(img, 5) # 中值滤波
#展示所有的
res = np.hstack((img,blur,box,aussian,median))
#加上这一句就可以调整窗口大小
cv2.namedWindow("median vs average",cv2.WINDOW_NORMAL);
cv2.imshow('median vs average', res)
cv2.waitKey(0)
cv2.destroyAllWindows()
#通常都是二值的图像来做腐蚀操作。腐蚀的大概意思就是往里面缩一些。
import cv2
import numpy as np
#灰度化
img_gray = cv2.imread('my.jpg',cv2.IMREAD_GRAYSCALE)
#img = cv2.imread('my.jpg')
#img_gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
#二值化
ret, thresh = cv2.threshold(img_gray, 127, 255, cv2.THRESH_BINARY)
kernel = np.ones((3, 5), np.uint8)
erosion = cv2.erode(thresh,kernel,iterations = 1) #迭代次数表示做几次腐蚀操作
#展示所有的
res = np.hstack((img_gray,thresh,erosion))
#加上这一句就可以调整窗口大小
cv2.namedWindow("erosion",cv2.WINDOW_NORMAL);
cv2.imshow('erosion', res)
cv2.waitKey(0)
cv2.destroyAllWindows()
import cv2
import numpy as np
#灰度化
img_gray = cv2.imread('my.jpg',cv2.IMREAD_GRAYSCALE)
#img = cv2.imread('my.jpg')
#img_gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
#二值化
ret, thresh = cv2.threshold(img_gray, 127, 255, cv2.THRESH_BINARY)
kernel = np.ones((3, 5), np.uint8)
dilate = cv2.dilate(thresh, kernel, iterations=1)#迭代次数表示做几次膨胀操作
#展示所有的
res = np.hstack((img_gray,thresh,dilate))
#加上这一句就可以调整窗口大小
cv2.namedWindow("dilate",cv2.WINDOW_NORMAL);
cv2.imshow('dilate', res)
cv2.waitKey(0)
cv2.destroyAllWindows()
#开运算消除小物体(白色)
import cv2
import numpy as np
#灰度化
img_gray = cv2.imread('my.jpg',cv2.IMREAD_GRAYSCALE)
#img = cv2.imread('my.jpg')
#img_gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
#二值化
ret, thresh = cv2.threshold(img_gray, 127, 255, cv2.THRESH_BINARY)
kernel = np.ones((5,5), np.uint8)
opening = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel)
#展示所有的
res = np.hstack((img_gray,thresh,opening))
#加上这一句就可以调整窗口大小
cv2.namedWindow("opening",cv2.WINDOW_NORMAL);
cv2.imshow('opening', res)
cv2.waitKey(0)
cv2.destroyAllWindows()
#闭运算消除小型黑洞
import cv2
import numpy as np
#灰度化
img_gray = cv2.imread('my.jpg',cv2.IMREAD_GRAYSCALE)
#img = cv2.imread('my.jpg')
#img_gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
#二值化
ret, thresh = cv2.threshold(img_gray, 127, 255, cv2.THRESH_BINARY)
kernel = np.ones((5,5), np.uint8)
closing = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel)
#展示所有的
res = np.hstack((img_gray,thresh,closing))
#加上这一句就可以调整窗口大小
cv2.namedWindow("closing",cv2.WINDOW_NORMAL);
cv2.imshow('closing', res)
cv2.waitKey(0)
cv2.destroyAllWindows()
#梯度运算凸显出边缘
import cv2
import numpy as np
#灰度化
img_gray = cv2.imread('my.jpg',cv2.IMREAD_GRAYSCALE)
#二值化
ret, thresh = cv2.threshold(img_gray, 127, 255, cv2.THRESH_BINARY)
kernel = np.ones((2,2),np.uint8)
gradient = cv2.morphologyEx(thresh, cv2.MORPH_GRADIENT, kernel)
#展示所有的
res = np.hstack((img_gray,thresh,gradient))
#加上这一句就可以调整窗口大小
cv2.namedWindow("gradient",cv2.WINDOW_NORMAL);
cv2.imshow('gradient', res)
cv2.waitKey(0)
cv2.destroyAllWindows()
#礼帽用来分离比邻近点亮一些的斑块
import cv2
import numpy as np
#灰度化
img_gray = cv2.imread('my.jpg',cv2.IMREAD_GRAYSCALE)
#二值化
ret, thresh = cv2.threshold(img_gray, 127, 255, cv2.THRESH_BINARY)
kernel = np.ones((7,7),np.uint8)
tophat = cv2.morphologyEx(thresh, cv2.MORPH_TOPHAT, kernel)
#展示所有的
res = np.hstack((img_gray,thresh,tophat))
#加上这一句就可以调整窗口大小
cv2.namedWindow("tophat",cv2.WINDOW_NORMAL);
cv2.imshow('tophat', res)
cv2.waitKey(0)
cv2.destroyAllWindows()
#黑帽用来分离比邻近点暗一些的斑块
import cv2
import numpy as np
#灰度化
img_gray = cv2.imread('my.jpg',cv2.IMREAD_GRAYSCALE)
#二值化
ret, thresh = cv2.threshold(img_gray, 127, 255, cv2.THRESH_BINARY)
kernel = np.ones((7,7),np.uint8)
blackhat = cv2.morphologyEx(thresh,cv2.MORPH_BLACKHAT, kernel)
#展示所有的
res = np.hstack((img_gray,thresh,blackhat))
#加上这一句就可以调整窗口大小
cv2.namedWindow("blackhat",cv2.WINDOW_NORMAL);
cv2.imshow('blackhat', res)
cv2.waitKey(0)
cv2.destroyAllWindows()
import cv2
import numpy as np
def cv_show(img,name):
cv2.imshow(name,img)
cv2.waitKey()
cv2.destroyAllWindows()
img = cv2.imread('my.jpg',cv2.IMREAD_GRAYSCALE)
#canny算子
canny=cv2.Canny(img,80,150)
#sobel算子
#dst = cv2.Sobel(src, ddepth, dx, dy, ksize)
#ddepth:图像的深度,一般取-1。
#dx和dy分别表示水平和竖直方向
#ksize是Sobel算子的大小
#白到黑是正数,黑到白就是负数了,所有的负数会被截断成0,所以要取绝对值。
#sobel算子 能够捕获更加细致的纹理信息。
sobelx = cv2.Sobel(img,cv2.CV_64F,1,0,ksize=3)
sobelx = cv2.convertScaleAbs(sobelx)
sobely = cv2.Sobel(img,cv2.CV_64F,0,1,ksize=3)
sobely = cv2.convertScaleAbs(sobely)
sobelxy = cv2.addWeighted(sobelx,0.5,sobely,0.5,0)
#Scharr算子
scharrx = cv2.Scharr(img,cv2.CV_64F,1,0)
scharrx = cv2.convertScaleAbs(scharrx)
scharry = cv2.Scharr(img,cv2.CV_64F,0,1)
scharry = cv2.convertScaleAbs(scharry)
scharrxy = cv2.addWeighted(scharrx,0.5,scharry,0.5,0)
#laplacian算子
laplacian = cv2.Laplacian(img,cv2.CV_64F)
laplacian = cv2.convertScaleAbs(laplacian)
res = np.hstack((canny,sobelxy,scharrxy,laplacian))
cv_show(res,'res')
import cv2
import numpy as np
def cv_show(img,name):
cv2.imshow(name,img)
cv2.waitKey()
cv2.destroyAllWindows()
img=cv2.imread("my.jpg")
cv_show(img,'img')
#高斯金字塔:向上采样方法(放大)
up=cv2.pyrUp(img)
cv_show(up,'up')
#高斯金字塔:向下采样方法(缩小)
down=cv2.pyrDown(img)
cv_show(down,'down')
#拉普拉斯金字塔
down=cv2.pyrDown(img)
down_up=cv2.pyrUp(down)
l_1=img-down_up
cv_show(l_1,'l_1')
#均值滤波,二值化,以及形态学等操作的顺序要根据不同场景的图像调整次序
import cv2
import numpy as np
img = cv2.imread('bee.jpg')
#灰度化
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
#Sobel边缘检测
sobelx = cv2.Sobel(img_gray,cv2.CV_64F,1,0,ksize=3)
sobely = cv2.Sobel(img_gray,cv2.CV_64F,0,1,ksize=3)
gradient = cv2.subtract(sobelx, sobely)
gradient = cv2.convertScaleAbs(gradient)
#均值滤波
blurred = cv2.blur(gradient , (9, 9))
#findContours(_,_,_)
#第二个参数
#cv2.RETR_EXTERNAL表示只检测外轮廓
#cv2.RETR_LIST检测的轮廓不建立等级关系
#cv2.RETR_CCOMP建立两个等级的轮廓,上面的一层为外边界,里面的一层为内孔的边界信息。如果内孔内还有一个连通物体,这个物体的边界也在顶层。
#cv2.RETR_TREE建立一个等级树结构的轮廓。
#第三个参数
#cv2.CHAIN_APPROX_SIMPLE 压缩水平方向,垂直方向,对角线方向的元素,只保留该方向的终点坐标(矩形只需四顶点)
#cv2.CHAIN_APPROX_TC89_L1 使用teh-Chinl chain 近似算法
#CV_CHAIN_APPROX_TC89_KCOS 使用teh-Chinl chain 近似算法
#cv2.CHAIN_APPROX_NONE 存储所有的轮廓点,相邻的两个点的像素位置差不超过1
#重点 寻找轮廓
(cnts, _) = cv2.findContours(blurred.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
#将轮廓按大小降序排序
c = sorted(cnts, key=cv2.contourArea, reverse=True)[0]
#计算最小斜矩形
rect = cv2.minAreaRect(c)
box = np.int0(cv2.boxPoints(rect))
#画出轮廓
cv2.drawContours(img,[box], -1, (0, 255, 0), 2)
cnt = cnts[0] #取第几个轮廓
print(cv2.arcLength(cnt,True))#周长,True表示闭合的
#边界矩形
area=cv2.contourArea(cnt)#面积
x,y,w,h = cv2.boundingRect(cnt)
cv2.rectangle(img,(x,y),(x+w,y+h),(0,0,255),2)
rect_area = w * h
extent = float(area) / rect_area
print ('轮廓面积',area,'边界矩形',rect_area,'轮廓面积与边界矩形比',extent)
#外接圆
(x,y),radius = cv2.minEnclosingCircle(cnt)
center = (int(x),int(y))
radius = int(radius)
cv2.circle(img,center,radius,(255,0,0),2)
#展示所有的
res = np.hstack((img_gray,gradient,blurred))
cv2.namedWindow("res",cv2.WINDOW_NORMAL);
cv2.imshow("res", res)
cv2.namedWindow("img",cv2.WINDOW_NORMAL);
cv2.imshow("img", img)
cv2.waitKey(0)
cv2.destroyAllWindows()
import cv2
import numpy as np
# 蓝色的HSV值
blue = np.uint8([[[255, 0, 0]]])
hsv_blue = cv2.cvtColor(blue, cv2.COLOR_BGR2HSV)
#print(hsv_blue) # [[[120 255 255]]]
# 追踪蓝色物体
capture = cv2.VideoCapture(0)
# 蓝色的范围,不同光照条件下不一样,可灵活调整
lower_blue = np.array([100, 110, 110])
upper_blue = np.array([130, 255, 255])
while(True):
# 1.捕获视频中的一帧
ret, frame = capture.read()
# 2.从BGR转换到HSV
hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
# 3.inRange():介于lower/upper之间的为白色,其余黑色
mask = cv2.inRange(hsv, lower_blue, upper_blue)
# 4.只保留原图中的蓝色部分
res = cv2.bitwise_and(frame, frame, mask=mask)
img_gray = cv2.cvtColor(res, cv2.COLOR_BGR2GRAY)
#Sobel边缘检测
sobelx = cv2.Sobel(img_gray,cv2.CV_64F,1,0,ksize=3)
sobely = cv2.Sobel(img_gray,cv2.CV_64F,0,1,ksize=3)
gradient = cv2.subtract(sobelx, sobely)
gradient = cv2.convertScaleAbs(gradient)
#均值滤波
blurred = cv2.blur(gradient , (9, 9))
#重点 寻找轮廓,opencv3版本
(_,cnts, _) = cv2.findContours(blurred.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
#opencv4版本
#(cnts, _) = cv2.findContours(blurred.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
#将轮廓按大小降序排序
c = sorted(cnts, key=cv2.contourArea, reverse=True)[0]
#计算最小斜矩形
rect = cv2.minAreaRect(c)
box = np.int0(cv2.boxPoints(rect))
#画出轮廓
cv2.drawContours(frame,[box], -1, (0, 255, 0), 2)
cv2.imshow('frame', frame)
cv2.imshow('mask', mask)
cv2.imshow('res', res)
if cv2.waitKey(1) == ord('q'):
break
import cv2
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread('my.jpg',0) #0表示灰度图
#1.直方图
hist = cv2.calcHist([img],[0],None,[256],[0,256])
plt.hist(img.ravel(),256);
plt.show()
#2.直方图均衡化
equ = cv2.equalizeHist(img)
plt.hist(equ.ravel(),256)
plt.show()
#3.自适应直方图均衡化
#将图像划分为多个小格子,然后对其进行均衡化处理,再对每个小格子的图像边界处理一下:
clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8))
res_clahe = clahe.apply(img)
plt.hist(res_clahe.ravel(),256)
plt.show()
#4.灰度图,直方图均衡化后的图,自适应直方图均衡化后的图 展示
res = np.hstack((img,equ,res_clahe))
cv2.imshow('res',res)
cv2.waitKey(0)
cv2.destroyAllWindows()
#5.b g r分布图
img2 = cv2.imread('my.jpg')
color = ('b','g','r')
for i,col in enumerate(color):
histr = cv2.calcHist([img2],[i],None,[256],[0,256])
plt.plot(histr,color = col)
plt.xlim([0,256])
plt.show()
#opencv中主要就是cv2.dft()和cv2.idft(),输入图像需要先转换成np.float32 格式。
#得到的结果中频率为0的部分会在左上角,通常要转换到中心位置,可以通过shift变换来实现。
#cv2.dft()返回的结果是双通道的(实部,虚部),通常还需要转换成图像格式才能展示(0,255)
#1.dft
import numpy as np
import cv2
from matplotlib import pyplot as plt
img = cv2.imread('my.jpg',0)
img_float32 = np.float32(img)
dft = cv2.dft(img_float32, flags = cv2.DFT_COMPLEX_OUTPUT)
dft_shift = np.fft.fftshift(dft)
# 得到灰度图能表示的形式
magnitude_spectrum = 20*np.log(cv2.magnitude(dft_shift[:,:,0],dft_shift[:,:,1]))
plt.subplot(121),plt.imshow(img, cmap = 'gray')
plt.title('Input Image'), plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(magnitude_spectrum, cmap = 'gray')
plt.title('Magnitude Spectrum'), plt.xticks([]), plt.yticks([])
plt.show()
#idft_低通滤波
import numpy as np
import cv2
from matplotlib import pyplot as plt
img = cv2.imread('my.jpg',0)
img_float32 = np.float32(img)
dft = cv2.dft(img_float32, flags = cv2.DFT_COMPLEX_OUTPUT)
dft_shift = np.fft.fftshift(dft)
rows, cols = img.shape
crow, ccol = int(rows/2) , int(cols/2) # 中心位置
# 低通滤波
mask = np.zeros((rows, cols, 2), np.uint8)
mask[crow-30:crow+30, ccol-30:ccol+30] = 1
# IDFT
fshift = dft_shift*mask
f_ishift = np.fft.ifftshift(fshift)
img_back = cv2.idft(f_ishift)
img_back = cv2.magnitude(img_back[:,:,0],img_back[:,:,1])
plt.subplot(121),plt.imshow(img, cmap = 'gray')
plt.title('Input Image'), plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(img_back, cmap = 'gray')
plt.title('Result'), plt.xticks([]), plt.yticks([])
plt.show()
#idft_高通滤波
import numpy as np
import cv2
from matplotlib import pyplot as plt
img = cv2.imread('my.jpg',0)
img_float32 = np.float32(img)
dft = cv2.dft(img_float32, flags = cv2.DFT_COMPLEX_OUTPUT)
dft_shift = np.fft.fftshift(dft)
rows, cols = img.shape
crow, ccol = int(rows/2) , int(cols/2) # 中心位置
# 高通滤波
mask = np.ones((rows, cols, 2), np.uint8)
mask[crow-30:crow+30, ccol-30:ccol+30] = 0
# IDFT
fshift = dft_shift*mask
f_ishift = np.fft.ifftshift(fshift)
img_back = cv2.idft(f_ishift)
img_back = cv2.magnitude(img_back[:,:,0],img_back[:,:,1])
plt.subplot(121),plt.imshow(img, cmap = 'gray')
plt.title('Input Image'), plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(img_back, cmap = 'gray')
plt.title('Result'), plt.xticks([]), plt.yticks([])
plt.show()
import cv2
import numpy as np
img = cv2.imread('chessboard.png')
# 1. Harris角点检测基于灰度图像
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 2. Harris角点检测
dst = cv2.cornerHarris(gray, 2, 3, 0.04)
# 腐蚀一下,便于标记
dst = cv2.dilate(dst, None)
# 3. 角点标记为红色
img[dst > 0.01 * dst.max()] = [0, 255, 255]
cv2.imshow('harris', img)
cv2.waitKey()
cv2.destroyAllWindows()
import cv2
import numpy as np
img = cv2.imread('chessboard.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# Shi-Tomasi角点检测 速度相比Harris有所提升,可以直接得到角点坐标
corners = cv2.goodFeaturesToTrack(gray, 20, 0.01, 10)
corners = np.int0(corners) # 12个角点坐标
for i in corners:
# 压缩至一维:[[62,64]]->[62,64]
x, y = i.ravel()
cv2.circle(img, (x, y), 4, (0, 0, 255), -1)
cv2.imshow('shi_tomasi', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
#sift已经被申请专利了,所以,在opencv3.4.3.16 版本后,这个功能就不能用了。
#解决方法版本回退
#sudo pip uninstall opencv-python
#sudo pip uninstall opencv-contrib-python
#sudo pip install opencv-python==3.4.2.16
#sudo pip install opencv-contrib-python==3.4.2.16
import cv2
import numpy as np
img = cv2.imread('chessboard.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
sift = cv2.xfeatures2d.SIFT_create()
kp = sift.detect(gray, None)
cv2.drawKeypoints(gray, kp, img,(0,255,0), flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
cv2.imshow('sift.jpg', img)
cv2.waitKey()
cv2.destroyAllWindows()
import cv2
import numpy as np
from matplotlib import pyplot as plt
# 1.模板匹配
img = cv2.imread('lena.jpg', 0)
template = cv2.imread('face.jpg', 0)
h, w = template.shape[:2] # rows->h, cols->w
# 6种匹配方法
methods = ['cv2.TM_CCOEFF', 'cv2.TM_CCOEFF_NORMED', 'cv2.TM_CCORR',
'cv2.TM_CCORR_NORMED', 'cv2.TM_SQDIFF', 'cv2.TM_SQDIFF_NORMED']
for meth in methods:
img2 = img.copy()
# 匹配方法的真值
method = eval(meth)
res = cv2.matchTemplate(img, template, method)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)
# 如果是平方差匹配TM_SQDIFF或归一化平方差匹配TM_SQDIFF_NORMED,取最小值
if method in [cv2.TM_SQDIFF, cv2.TM_SQDIFF_NORMED]:
top_left = min_loc
else:
top_left = max_loc
bottom_right = (top_left[0] + w, top_left[1] + h)
# 画矩形
cv2.rectangle(img2, top_left, bottom_right, 255, 2)
plt.subplot(121), plt.imshow(res, cmap='gray')
plt.xticks([]), plt.yticks([]) # 隐藏坐标轴
plt.subplot(122), plt.imshow(img2, cmap='gray')
plt.xticks([]), plt.yticks([])
plt.suptitle(meth)
plt.show()
# 2.匹配多个物体
img_rgb = cv2.imread('mario.jpg')
img_gray = cv2.cvtColor(img_rgb, cv2.COLOR_BGR2GRAY)
template = cv2.imread('mario_coin.jpg', 0)
h, w = template.shape[:2]
res = cv2.matchTemplate(img_gray, template, cv2.TM_CCOEFF_NORMED)
threshold = 0.8
# 取匹配程度大于%80的坐标
loc = np.where(res >= threshold)
for pt in zip(*loc[::-1]): # *号表示可选参数
bottom_right = (pt[0] + w, pt[1] + h)
cv2.rectangle(img_rgb, pt, bottom_right, (0, 0, 255), 2)
cv2.imshow('img_rgb', img_rgb)
cv2.waitKey(0)
# 3.有关几个函数的说明:
x = np.arange(9.).reshape(3, 3)
print(np.where(x > 5))
# 结果:(array([2, 2, 2]), array([0, 1, 2]))
x = [1, 2, 3]
y = [4, 5, 6]
print(list(zip(x, y))) # [(1, 4), (2, 5), (3, 6)]
import cv2
import numpy as np
import matplotlib.pyplot as plt
img1 = cv2.imread('box.png', 0)
img2 = cv2.imread('box_in_scene.png', 0)
def cv_show(name,img):
cv2.imshow(name, img)
cv2.waitKey(0)
cv2.destroyAllWindows()
# cv_show('img1',img1)
# cv_show('img2',img2)
sift = cv2.xfeatures2d.SIFT_create()
kp1, des1 = sift.detectAndCompute(img1, None)
kp2, des2 = sift.detectAndCompute(img2, None)
bf = cv2.BFMatcher()
matches = bf.knnMatch(des1, des2, k=2)
good = []
for m, n in matches:
if m.distance < 0.75 * n.distance:
good.append([m])
img3 = cv2.drawMatchesKnn(img1,kp1,img2,kp2,good,None,flags=2)
cv_show('img3',img3)
#Stitcher.py
import numpy as np
import cv2
class Stitcher:
#拼接函数
def stitch(self, images, ratio=0.75, reprojThresh=4.0,showMatches=False):
#获取输入图片
(imageB, imageA) = images
#检测A、B图片的SIFT关键特征点,并计算特征描述子
(kpsA, featuresA) = self.detectAndDescribe(imageA)
(kpsB, featuresB) = self.detectAndDescribe(imageB)
# 匹配两张图片的所有特征点,返回匹配结果
M = self.matchKeypoints(kpsA, kpsB, featuresA, featuresB, ratio, reprojThresh)
# 如果返回结果为空,没有匹配成功的特征点,退出算法
if M is None:
return None
# 否则,提取匹配结果
# H是3x3视角变换矩阵
(matches, H, status) = M
# 将图片A进行视角变换,result是变换后图片
result = cv2.warpPerspective(imageA, H, (imageA.shape[1] + imageB.shape[1], imageA.shape[0]))
self.cv_show('result', result)
# 将图片B传入result图片最左端
result[0:imageB.shape[0], 0:imageB.shape[1]] = imageB
self.cv_show('result', result)
# 检测是否需要显示图片匹配
if showMatches:
# 生成匹配图片
vis = self.drawMatches(imageA, imageB, kpsA, kpsB, matches, status)
# 返回结果
return (result, vis)
# 返回匹配结果
return result
def cv_show(self,name,img):
cv2.imshow(name, img)
cv2.waitKey(0)
cv2.destroyAllWindows()
def detectAndDescribe(self, image):
# 将彩色图片转换成灰度图
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# 建立SIFT生成器
descriptor = cv2.xfeatures2d.SIFT_create()
# 检测SIFT特征点,并计算描述子
(kps, features) = descriptor.detectAndCompute(image, None)
# 将结果转换成NumPy数组
kps = np.float32([kp.pt for kp in kps])
# 返回特征点集,及对应的描述特征
return (kps, features)
def matchKeypoints(self, kpsA, kpsB, featuresA, featuresB, ratio, reprojThresh):
# 建立暴力匹配器
matcher = cv2.BFMatcher()
# 使用KNN检测来自A、B图的SIFT特征匹配对,K=2
rawMatches = matcher.knnMatch(featuresA, featuresB, 2)
matches = []
for m in rawMatches:
# 当最近距离跟次近距离的比值小于ratio值时,保留此匹配对
if len(m) == 2 and m[0].distance < m[1].distance * ratio:
# 存储两个点在featuresA, featuresB中的索引值
matches.append((m[0].trainIdx, m[0].queryIdx))
# 当筛选后的匹配对大于4时,计算视角变换矩阵
if len(matches) > 4:
# 获取匹配对的点坐标
ptsA = np.float32([kpsA[i] for (_, i) in matches])
ptsB = np.float32([kpsB[i] for (i, _) in matches])
# 计算视角变换矩阵
(H, status) = cv2.findHomography(ptsA, ptsB, cv2.RANSAC, reprojThresh)
# 返回结果
return (matches, H, status)
# 如果匹配对小于4时,返回None
return None
def drawMatches(self, imageA, imageB, kpsA, kpsB, matches, status):
# 初始化可视化图片,将A、B图左右连接到一起
(hA, wA) = imageA.shape[:2]
(hB, wB) = imageB.shape[:2]
vis = np.zeros((max(hA, hB), wA + wB, 3), dtype="uint8")
vis[0:hA, 0:wA] = imageA
vis[0:hB, wA:] = imageB
# 联合遍历,画出匹配对
for ((trainIdx, queryIdx), s) in zip(matches, status):
# 当点对匹配成功时,画到可视化图上
if s == 1:
# 画出匹配对
ptA = (int(kpsA[queryIdx][0]), int(kpsA[queryIdx][1]))
ptB = (int(kpsB[trainIdx][0]) + wA, int(kpsB[trainIdx][1]))
cv2.line(vis, ptA, ptB, (0, 255, 0), 1)
# 返回可视化结果
return vis
#ImageStiching.py
from Stitcher import Stitcher
import cv2
# 读取拼接图片
imageA = cv2.imread("left_01.png")
imageB = cv2.imread("right_01.png")
# 把图片拼接成全景图
stitcher = Stitcher()
(result, vis) = stitcher.stitch([imageA, imageB], showMatches=True)
# 显示所有图片
cv2.imshow("Image A", imageA)
cv2.imshow("Image B", imageB)
cv2.imshow("Keypoint Matches", vis)
cv2.imshow("Result", result)
cv2.waitKey(0)
cv2.destroyAllWindows()
# ex2tron's blog:
# http://ex2tron.wang
import cv2
import numpy as np
# 1. 霍夫直线变换
img = cv2.imread('shapes.jpg')
cv2.imshow('src', img)
drawing = np.zeros(img.shape[:], dtype=np.uint8) # 创建画板
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
edges = cv2.Canny(gray, 50, 150)
# 霍夫直线变换
lines = cv2.HoughLines(edges, 0.8, np.pi / 180, 90)
# 将检测的线画出来(注意是极坐标噢)
for line in lines:
rho, theta = line[0]
a = np.cos(theta)
b = np.sin(theta)
x0 = a * rho
y0 = b * rho
x1 = int(x0 + 1000 * (-b))
y1 = int(y0 + 1000 * (a))
x2 = int(x0 - 1000 * (-b))
y2 = int(y0 - 1000 * (a))
cv2.line(drawing, (x1, y1), (x2, y2), (0, 0, 255))
cv2.imshow('hough lines', np.hstack((img, drawing)))
cv2.waitKey(0)
# 2. 统计概率霍夫线变换
drawing = np.zeros(img.shape[:], dtype=np.uint8)
lines = cv2.HoughLinesP(edges, 0.8, np.pi / 180, 90,
minLineLength=50, maxLineGap=10)
# 将检测的线画出来
for line in lines:
x1, y1, x2, y2 = line[0]
cv2.line(drawing, (x1, y1), (x2, y2), (0, 255, 0), 1, lineType=cv2.LINE_AA)
cv2.imshow('probabilistic hough lines', np.hstack((img, drawing)))
cv2.waitKey(0)
# 3. 霍夫圆变换
drawing = np.zeros(img.shape[:], dtype=np.uint8)
circles = cv2.HoughCircles(edges, cv2.HOUGH_GRADIENT, 1, 20, param2=30)
circles = np.int0(np.around(circles))
# 将检测的圆画出来
for i in circles[0, :]:
cv2.circle(drawing, (i[0], i[1]), i[2], (0, 255, 0), 2) # 画出外圆
cv2.circle(drawing, (i[0], i[1]), 2, (0, 0, 255), 3) # 画出圆心
cv2.imshow('circles', np.hstack((img, drawing)))
cv2.waitKey(0)
import cv2
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread('drawing.jpg')
rows, cols = img.shape[:2]
# 1.仿射变换
# 变换前的三个点
pts1 = np.float32([[50, 65], [150, 65], [210, 210]])
# 变换后的三个点
pts2 = np.float32([[50, 100], [150, 65], [100, 250]])
# 生成变换矩阵,维数:2*3
M = cv2.getAffineTransform(pts1, pts2)
dst = cv2.warpAffine(img, M, (cols, rows))
plt.subplot(121), plt.imshow(img), plt.title('input')
plt.subplot(122), plt.imshow(dst), plt.title('output')
plt.show()
# 2.透视变换
img = cv2.imread('card.jpg')
# 原图中卡片的四个角点
pts1 = np.float32([[148, 80], [437, 114], [94, 247], [423, 288]])
# 变换后分别在左上、右上、左下、右下四个点
pts2 = np.float32([[0, 0], [320, 0], [0, 178], [320, 178]])
# 生成透视变换矩阵
M = cv2.getPerspectiveTransform(pts1, pts2)
# 进行透视变换,参数3是目标图像大小
dst = cv2.warpPerspective(img, M, (320, 178))
# matplotlib默认以RGB通道显示,所以需要用[:, :, ::-1]翻转一下
plt.subplot(121), plt.imshow(img[:, :, ::-1]), plt.title('input')
plt.subplot(122), plt.imshow(dst[:, :, ::-1]), plt.title('output')
plt.show()
import cv2
import numpy as np
import math
def fourier_demo():
#1、灰度化读取文件,
img = cv2.imread('english.png',0)
#2、图像延扩
h, w = img.shape[:2]
new_h = cv2.getOptimalDFTSize(h)
new_w = cv2.getOptimalDFTSize(w)
right = new_w - w
bottom = new_h - h
nimg = cv2.copyMakeBorder(img, 0, bottom, 0, right, borderType=cv2.BORDER_CONSTANT, value=0)
cv2.imshow('src ', nimg)
#3、执行傅里叶变换,并过得频域图像
f = np.fft.fft2(nimg)
fshift = np.fft.fftshift(f)
magnitude = np.log(np.abs(fshift))
#二值化
magnitude_uint = magnitude.astype(np.uint8)
ret, thresh = cv2.threshold(magnitude_uint, 11, 255, cv2.THRESH_BINARY)
print(ret)
cv2.imshow('thresh', thresh)
print(thresh.dtype)
#霍夫直线变换
lines = cv2.HoughLinesP(thresh, 2, np.pi/180, 30, minLineLength=40, maxLineGap=100)
print(len(lines))
#创建一个新图像,标注直线
lineimg = np.ones(nimg.shape,dtype=np.uint8)
lineimg = lineimg * 255
piThresh = np.pi/180
pi2 = np.pi/2
print(piThresh)
for line in lines:
x1, y1, x2, y2 = line[0]
cv2.line(lineimg, (x1, y1), (x2, y2), (0, 255, 0), 2)
if x2 - x1 == 0:
continue
else:
theta = (y2 - y1) / (x2 - x1)
if abs(theta) < piThresh or abs(theta - pi2) < piThresh:
continue
else:
print(theta)
angle = math.atan(theta)
print(angle)
angle = angle * (180 / np.pi)
print(angle)
angle = (angle - 90)/(w/h)
print(angle)
center = (w//2, h//2)
M = cv2.getRotationMatrix2D(center, angle, 1.0)
rotated = cv2.warpAffine(img, M, (w, h), flags=cv2.INTER_CUBIC, borderMode=cv2.BORDER_REPLICATE)
cv2.imshow('line image', lineimg)
cv2.imshow('rotated', rotated)
fourier_demo()
cv2.waitKey(0)
cv2.destroyAllWindows()
额!肝一整天,终于肝完了!!!!>_< ========> ^_^