第 1 周
from skimage import data, color
from matplotlib import pyplot as plt
img = data.coffee()
# 將圖像轉換為灰度圖像
gray = color.rgb2gray(img)
plt.imshow(gray, cmap='gray')
plt.show()
# 將圖像從RGB顏色空間轉換為HSV顏色空間
hsv_img = color.convert_colorspace(img, 'RGB', 'HSV')
plt.imshow(hsv_img)
plt.show()
from skimage import data
from matplotlib import pyplot as plt
import numpy as np
img = data.coffee()
# 創(chuàng)建用于存儲灰度圖像的數(shù)組
max_gray = np.zeros(img.shape[0:2], dtype='uint8')
ave_gray = np.zeros(img.shape[0:2], dtype='uint8')
weight_gray = np.zeros(img.shape[0:2], dtype='uint8')
# 遍歷圖像的每個像素
for i in range(img.shape[0]):
for j in range(img.shape[1]):
r, g, b = img[i, j, :]
# 最大值法:取像素的最大值作為灰度值
max_gray[i, j] = max(r, g, b)
# 平均值法:將紅肺樟、綠、藍三個通道的值相加后除以3
ave_gray[i, j] = (r + g + b) / 3.0
# 加權平均法:使用固定的權重將紅、綠、藍三個通道的值加權求和
weight_gray[i, j] = 0.30 * r + 0.59 * g + 0.11 * b
# 設置字體為中文黑體
plt.rcParams['font.sans-serif'] = ['SimHei']
# 創(chuàng)建子圖并顯示原始彩色圖像以及三種灰度化結果
plt.subplot(221), plt.axis('off')
plt.imshow(img), plt.title('彩色圖像')
plt.subplot(222), plt.axis('off')
plt.imshow(max_gray, cmap='gray'), plt.title('最大值法')
plt.subplot(223), plt.axis('off')
plt.imshow(ave_gray, cmap='gray'), plt.title('平均值法')
plt.subplot(224), plt.axis('off')
plt.imshow(weight_gray, cmap='gray'), plt.title('加權平均法')
plt.show()
from skimage import io,color
from matplotlib import pyplot as plt
import numpy as np
image = io.imread('image\JJ.jpg')
r = image[:,:,0]
g = image[:,:,1]
b = image[:,:,2]
b_template = np.zeros(image.shape, dtype = 'uint8')
for i in range(b.shape[0]):
for j in range(b.shape[1]):
if b[i, j] <= 100:
b_template[i, j] = 1
image2 = image * b_template
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.subplot(221),plt.axis('off')
plt.imshow(image),plt.title('原始RGB圖像')
plt.subplot(222),plt.axis('off')
plt.imshow(b, cmap='gray'),plt.title('B分量')
plt.subplot(223),plt.axis('off')
plt.imshow(color.rgb2gray(b_template), cmap='gray')
plt.title('藍色通道模板')
plt.subplot(224),plt.axis('off')
plt.imshow(image2),plt.title('分割后的RGB圖像')
plt.show()
第 2 周
import numpy as np
from skimage import data, color
from matplotlib import pyplot as plt
def cov2d(img, window):
# 獲取窗口的尺寸
m, n = window.shape
# 獲取圖像的尺寸
h, w = img.shape
# 通過在邊界填充0灰度值來擴展圖像
img1 = np.zeros((h + m - 1, w + n - 1))
img1[(m-1)//2 : h+(m-1)//2, (n-1)//2 : (w+(n-1)//2)] = img
# 創(chuàng)建與原圖像大小相同的零矩陣
img2 = np.zeros(img.shape)
# 對圖像進行卷積操作
for i in range(img2.shape[0]):
for j in range(img2.shape[1]):
# 獲取當前窗口區(qū)域
temp = img1[i: i + m, j: j + n]
# 計算窗口區(qū)域與卷積核的乘積并求和
img2[i, j] = np.sum(np.multiply(temp, window))
return img2
img = data.chelsea()
img = color.rgb2gray(img)
# 定義一個3x3的平均濾波器
window = np.ones((3, 3)) / (3 ** 2)
# 對圖像進行卷積操作
new_img = cov2d(img, window)
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.subplot(121), plt.axis('off')
plt.imshow(img, cmap='gray'), plt.title('原圖像')
plt.subplot(122), plt.axis('off')
plt.imshow(new_img, cmap='gray'), plt.title('3核平滑卷積結果')
plt.show()
import numpy as np
from scipy import signal
from skimage import data
import matplotlib.pyplot as plt
# 定義二維灰度圖像的空間濾波函數(shù)
def correl2d(img, window):
# 使用濾波器實現(xiàn)圖像的空間相關
# mode='same' 表示輸出尺寸等于輸入尺寸
# boundary='fill' 表示濾波前古瓤,用常量值填充原圖像的邊緣向拆,默認常量
s = signal.correlate2d(img, window, mode='same', boundary='fill')
return s
img = data.camera()
window1 = np.ones((3, 3)) / (3 ** 2)
window2 = np.ones((5, 5)) / (5 ** 2)
window3 = np.ones((9, 9)) / (9 ** 2)
new_img1 = correl2d(img, window1)
new_img2 = correl2d(img, window2)
new_img3 = correl2d(img, window3)
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.subplot(221), plt.axis('off')
plt.imshow(img, cmap='gray'), plt.title('原圖像')
plt.subplot(222), plt.axis('off')
plt.imshow(new_img1, cmap='gray'), plt.title('3*3')
plt.subplot(223), plt.axis('off')
plt.imshow(new_img2, cmap='gray'), plt.title('5*5')
plt.subplot(224), plt.axis('off')
plt.imshow(new_img3, cmap='gray'), plt.title('9*9')
plt.show()
from scipy import ndimage
from skimage import data, color, util
from matplotlib import pyplot as plt
img = color.rgb2gray(data.astronaut())
noise_img = util.random_noise(img, mode='s&p',seed=None,clip=True) # 對圖像加入椒鹽噪聲
new_img= ndimage.median_filter(noise_img,(3, 3)) # 中值濾波
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.subplot(131),plt.axis('off')
plt.imshow(img, cmap = 'gray'),plt.title('原圖像')
plt.subplot(132),plt.axis('off')
plt.imshow(noise_img, cmap = 'gray'),plt.title('加噪圖像')
plt.subplot(133),plt.axis('off')
plt.imshow(new_img, cmap = 'gray'),plt.title('中值濾波')
plt.show()
第 3 周
import numpy as np
from scipy import signal
from skimage import data
from matplotlib import pyplot as plt
#定義二維灰度圖像的空間濾波函數(shù)
def cov2d(img, window):
s= signal.correlate2d(img, window, mode ='same',boundary ='fill')
return s
# img為原始圖像
img = data.camera()
window = np.ones((7,7))
img_blur = cov2d(img, window)
img_edge = img - img_blur
img_enhance = img + img_edge
# plt.rcParams['font.sans-serif'] = ['SimHei']
# plt.subplot(221),plt.axis('off')
# plt.imshow(img, cmap = 'gray'),plt.title('原圖像')
# plt.subplot(222),plt.axis('off')
# plt.imshow(img_blur, cmap = 'gray'),plt.title('模糊圖像')
# plt.subplot(223),plt.axis('off')
# plt.imshow(img_edge, cmap = 'gray'),plt.title('差值圖像')
# plt.subplot(224),plt.axis('off')
# plt.imshow(img_enhance, cmap = 'gray'),plt.title('銳化增強')
# plt.show()
plt.rcParams['font.sans-serif'] = ['SimHei']
k = [1, 2, 3, 4]
for r in k:
img_enhance = img + r * img_edge
plt.subplot(2, 2, r),plt.axis('off')
plt.imshow(img_enhance, cmap = 'gray'),plt.title(u'權重系數(shù)為{}'.format(r))
plt.show()
import math
import numpy as np
from scipy import signal
from skimage import data
from matplotlib import pyplot as plt
# 定義二維灰度圖像的空間濾波函數(shù)
def cov2d(img, window):
return signal.correlate2d(img, window, mode ='same',boundary ='fill')
img = data.camera()
window1 = np.array([[-1, 0], [1, 0]])
window2 = np.array([[-1, 1], [0, 0]])
img_h= cov2d(img, window1)
img_v= cov2d(img, window2)
img_hv= np.zeros(img.shape)
for i in range(img.shape[0]):
for j in range(img.shape[1]):
img_hv[i, j] = math.sqrt(img_h[i, j] ** 2 + img_v[i, j] ** 2)
plt.rcParams['font.sans-serif'] = ['SimHei']
c = [img, img_h, img_v, img_hv]
s = ['原圖像', '水平邊緣圖像', '豎直邊緣圖像', '梯度圖像']
for r in range(4):
plt.subplot(2, 2, r + 1),plt.axis('off')
plt.imshow(c[r], cmap = 'gray'),plt.title(s[r])
plt.show()
from skimage import data
import numpy as np
from matplotlib import pyplot as plt
img = data.camera()
ft = abs(np.fft.fft2(img)) # 快速傅里葉變換算法得到頻率分布
log = np.log(ft) # 對數(shù)顯示
shift = abs(np.fft.fftshift(ft)) # 將ft后的頻譜圖像平移
log_shift = np.log(shift) # 頻移后對數(shù)顯示
plt.rcParams['font.sans-serif'] = ['SimHei']
c = [ft, log, shift, log_shift]
s = ['傅里葉變換', '對數(shù)顯示', '頻譜圖像平移', '頻移后對數(shù)顯示']
for i in range(4):
plt.subplot(2, 2, i + 1)
plt.imshow(c[i], 'gray')
plt.title(s[i])
plt.show()
import numpy as np
import matplotlib.pyplot as plt
#實現(xiàn)圓孔低通濾波器
m,n = 256,256
mid_m, mid_n = int(m/2),int(n/2) #找到傅里葉頻譜圖的中心點
LowpassMask = np.zeros((m,n),np.uint8) #生成空矩陣朝捆,數(shù)據(jù)格式為uint8
rd = [10, 20, 50, 100]
c = 1
for r in rd:
for i in range(m):
for j in range(n):
d = np.sqrt((i-mid_m)**2 + (j-mid_n)**2)
if d <= r:
# 將距離頻譜中心小于D的部分低通信息設置為1鹤盒,屬于低通濾波
LowpassMask[i,j] = 1
plt.subplot(2, 2, c), plt.title('r={}'.format(r))
plt.imshow(LowpassMask,cmap='gray'),
c += 1
plt.show()
第 4 周
import numpy as np
from skimage import data, exposure
import matplotlib.pyplot as plt
# 從skimage加載咖啡圖像,并提取其第一個通道(灰度圖像)
img = data.coffee()[:, :, 0]
# 計算灰度圖像的直方圖的函數(shù)
def histogram(grayfig):
x = grayfig.shape[0]
y = grayfig.shape[1]
ret = np.zeros(256) # 初始化一個數(shù)組褐隆,用于存儲每個灰度級別的直方圖計數(shù)
for i in range(x):
for j in range(y):
ret[grayfig[i][j]] += 1 # 增加對應灰度級別的計數(shù)
return ret
# 使用自定義函數(shù)計算圖像的直方圖
GrayHist_1 = histogram(img)
# 使用skimage的內(nèi)置函數(shù)計算圖像的直方圖
GrayHist_2, bins = exposure.histogram(img)
plt.figure()
plt.subplot(311), plt.imshow(img, cmap='gray')
plt.subplot(312), plt.plot(GrayHist_1)
plt.subplot(313), plt.plot(GrayHist_2)
plt.show()
from skimage import data, exposure
import matplotlib.pyplot as plt
img = data.coffee()[:, :, 0]
img_hist, bins = exposure.histogram(img)
plt.figure(figsize=(4,6))
plt.subplot(311), plt.plot(bins, img_hist)
plt.subplot(312), plt.bar(bins, img_hist)
plt.subplot(313), plt.hist(img.flatten())
plt.show()
from skimage import data
import matplotlib.pyplot as plt
img = data.coffee()
img_r = img[:,:,0]
img_g = img[:,:,1]
img_b = img[:,:,2]
arr = img.flatten()
arr_r = img_r.flatten()
arr_g = img_g.flatten()
arr_b = img_b.flatten()
plt.figure(figsize=(6, 8)) # 調(diào)整圖像大小
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False # 修正參數(shù)名
plt.subplot(421), plt.axis('off'), plt.imshow(img), plt.title('原彩色圖像')
plt.subplot(422), plt.hist(arr, bins=256) # 修改直方圖的顏色
plt.subplot(423), plt.axis('off'), plt.imshow(img_r, cmap='gray'), plt.title('R通道')
plt.subplot(425), plt.axis('off'), plt.imshow(img_g, cmap='gray'), plt.title('G通道')
plt.subplot(427), plt.axis('off'), plt.imshow(img_b, cmap='gray'), plt.title('B通道')
plt.subplot(424), plt.hist(arr_r, bins=256, color='red')
plt.subplot(426), plt.hist(arr_g, bins=256, color='green')
plt.subplot(428), plt.hist(arr_b, bins=256, color='blue')
plt.show()
import numpy as np
import matplotlib.pyplot as plt
from skimage import data
# 繪制直方圖
def histogram(grayfig):
x = grayfig.shape[0] # 獲取圖像的高度
y = grayfig.shape[1] # 獲取圖像的寬度
ret = np.zeros(256) # 初始化直方圖數(shù)組污它,包含256個灰度級
for i in range(x): # 遍歷圖像的每一行
for j in range(y): # 遍歷圖像的每一列
k = grayfig[i][j] # 獲取像素點的灰度值
ret[k] = ret[k] + 1 # 統(tǒng)計對應灰度級的像素數(shù)量
return ret # 返回直方圖數(shù)組
# 繪制累積直方圖
def histogram_sum(grayfig):
x = grayfig.shape[0]
y = grayfig.shape[1]
ret = np.zeros(256)
for i in range(x):
for j in range(y):
k = grayfig[i][j]
ret[k] = ret[k] + 1
for k in range(256): # 遍歷所有灰度級
ret[k] = ret[k] + ret[k - 1] # 計算累積直方圖,累加每個灰度級的像素數(shù)量
return ret
img_r = data.coffee()[:, :, 0] # 讀取咖啡圖像的紅色通道
hist_r = histogram(img_r) # 計算咖啡圖像紅色通道的直方圖
hist_r = hist_r / hist_r.max() # 歸一化處理直方圖
histSum_r = histogram_sum(img_r) # 計算咖啡圖像紅色通道的累積直方圖
histSum_r = histSum_r / histSum_r.max() # 歸一化處理累積直方圖
plt.figure(figsize=(8, 4))
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.subplot(121), plt.title("普通直方圖"), plt.bar(range(256), hist_r)
plt.subplot(122), plt.title("累積直方圖"), plt.bar(range(256), histSum_r, color='y')
plt.show()
from skimage import data, exposure
import matplotlib.pyplot as plt
# 讀取咖啡圖像的紅色通道
img_r = data.coffee()[:,:,0]
# 計算紅色通道的直方圖
hist_r, bins = exposure.histogram(img_r)
# 計算紅色通道的累積直方圖
hist_sum_r, bins = exposure.cumulative_distribution(img_r)
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.subplot(221), plt.bar(bins, hist_r), plt.title("直方圖")
plt.subplot(222), plt.bar(bins, hist_sum_r, color='y'), plt.title("累加直方圖")
plt.subplot(223), plt.plot(bins, hist_r), plt.title("直方圖")
plt.subplot(224), plt.plot(bins, hist_sum_r, color='y'), plt.title("累加直方圖")
plt.show()
from skimage import data
import matplotlib.pyplot as plt
img_r = data.coffee()[:,:,0]
arr_r = img_r.flatten()
plt.figure(figsize=(8,4))
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.subplot(121), plt.title("直方圖")
plt.hist(arr_r,
bins=256, # 指定直方圖的組距
density=True, # 設置為頻率直方圖
# cumulative=True, # 積累直方圖
# color='y', # 指定填充色
# edgecolor='w', # 指定直方圖的邊界色
# label='直方圖' # 為直方圖呈現(xiàn)標簽
)
plt.subplot(122), plt.title("累加直方圖")
plt.hist(arr_r, # 繪圖數(shù)據(jù)
bins=256, # 指定直方圖的組距
density=True, # 設置為頻率直方圖
cumulative=True, # 積累直方圖
color='y', # 指定填充色
# edgecolor='w', # 指定直方圖的邊界色
# label='累加直方圖' # 為直方圖呈現(xiàn)標簽
)
plt.show()
import matplotlib.pyplot as plt
from skimage import data, exposure
reference = data.coffee() # 參考圖像
image = data.chelsea() # 待匹配圖像
# 對待匹配圖像進行直方圖匹配庶弃,使其與參考圖像的直方圖相匹配
matched = exposure.match_histograms(image, reference, multichannel=True)
# 創(chuàng)建繪圖窗口和子圖
fig, (ax1, ax2, ax3) = plt.subplots(nrows=1, ncols=3, figsize=(8, 3), sharex=True, sharey=True)
# 遍歷子圖并設置坐標軸關閉
for aa in (ax1, ax2, ax3):
aa.set_axis_off()
ax1.imshow(image), ax1.set_title('源圖像')
ax2.imshow(reference), ax2.set_title('參考圖像')
ax3.imshow(matched), ax3.set_title('匹配后圖像')
# 調(diào)整布局并顯示繪圖
plt.tight_layout(), plt.show()
第 5 周
import matplotlib.pyplot as plt
from skimage import data
from skimage.feature import graycomatrix, graycoprops
image = data.camera()
PATCH_SIZE=50
# 選擇圖像中的天空區(qū)域塊
sky_locations =[(54,48),(21,233),(90,380),(55,330)]
sky_patches =[]
for loc in sky_locations:
sky_patches.append(image[loc[0]:loc[0]+ PATCH_SIZE,loc[1]:loc[1]+ PATCH_SIZE])
#選擇圖像中的草地區(qū)域塊
grass_locations =[(387,186),(348,372),(330,447),(462,443)]
grass_patches = []
for loc in grass_locations:
grass_patches.append(image[loc[0]:loc[0]+ PATCH_SIZE,loc[1]:loc[1]+ PATCH_SIZE])
# plt.figure()
plt.imshow(image, cmap='gray')
for (y, x)in grass_locations:
plt.plot(x, y, 'gs')
for (y, x)in sky_locations:
plt.plot(x, y, 'bs')
plt.show()
import matplotlib.pyplot as plt
from skimage import data
from skimage.feature import graycomatrix, graycoprops
# 載入示例圖像
image = data.camera()
# 定義采樣區(qū)域大小
PATCH_SIZE = 50
# 天空區(qū)域位置
sky_locations = [(54, 48), (21, 233), (90, 380), (55, 330)]
sky_patches = []
for loc in sky_locations:
sky_patches.append(image[loc[0]:loc[0] + PATCH_SIZE, loc[1]:loc[1] + PATCH_SIZE])
# 草地區(qū)域位置
grass_locations = [(387, 186), (348, 372), (330, 447), (462, 443)]
grass_patches = []
for loc in grass_locations:
grass_patches.append(image[loc[0]:loc[0] + PATCH_SIZE, loc[1]:loc[1] + PATCH_SIZE])
# 創(chuàng)建畫布
plt.figure(figsize=(8, 5))
# 繪制天空區(qū)域
for i, patch in enumerate(sky_patches):
plt.subplot(2, len(sky_patches), i + 1)
plt.imshow(patch, cmap=plt.cm.gray, interpolation='nearest', vmin=0, vmax=255)
plt.title('Sky %d' % (i + 1))
# 繪制草地區(qū)域
for i, patch in enumerate(grass_patches):
plt.subplot(2, len(grass_patches), len(grass_patches) * 1 + i + 1)
plt.imshow(patch, cmap=plt.cm.gray, interpolation='nearest', vmin=0, vmax=255)
plt.title('Grass %d' % (i + 1))
# 顯示圖像
plt.show()
import matplotlib.pyplot as plt
from skimage import data
from skimage.feature import graycomatrix, graycoprops
# 載入示例圖像
image = data.camera()
# 定義采樣區(qū)域大小
PATCH_SIZE = 50
# 天空區(qū)域位置和草地區(qū)域位置
sky_locations = [(54, 48), (21, 233), (90, 380), (55, 330)]
grass_locations = [(387, 186), (348, 372), (330, 447), (462, 443)]
# 提取天空和草地區(qū)域
sky_patches, grass_patches = [], []
for loc in sky_locations:
sky_patches.append(image[loc[0]:loc[0] + PATCH_SIZE, loc[1]:loc[1] + PATCH_SIZE])
for loc in grass_locations:
grass_patches.append(image[loc[0]:loc[0] + PATCH_SIZE, loc[1]:loc[1] + PATCH_SIZE])
# 計算天空區(qū)域的灰度共生矩陣屬性
xs, ys = [], []
for patch in sky_patches:
glcm = graycomatrix(patch, [5], [0], 256, symmetric=True, normed=True)
xs.append(graycoprops(glcm, 'dissimilarity')[0, 0])
ys.append(graycoprops(glcm, 'correlation')[0, 0])
# 計算草地區(qū)域的灰度共生矩陣屬性
xg, yg = [], []
for patch in grass_patches:
glcm = graycomatrix(patch, [5], [0], 256, symmetric=True, normed=True)
xg.append(graycoprops(glcm, 'dissimilarity')[0, 0])
yg.append(graycoprops(glcm, 'correlation')[0, 0])
# 繪制散點圖
plt.figure()
plt.plot(xs, ys, 'bo', label='Sky')
plt.plot(xg, yg, 'go', label='Grass')
plt.xlabel('GLCM Dissimilarity')
plt.ylabel('GLCM Correlation')
plt.legend()
plt.show()
from skimage import io, color
import skimage.feature
import matplotlib.pyplot as plt
# image = data.coffee()
# image = io.imread('brick.jpg')
# image = io.imread('image/face.jpg')
image = io.imread('../image/face2.jpg')
# 將圖像轉換為灰度圖
img = color.rgb2gray(image)
# 計算局部二值模式特征
texture = skimage.feature.local_binary_pattern(img, 8, 1.0, method='default')
# 繪制圖像和特征圖
plt.figure()
plt.subplot(121), plt.imshow(img, cmap='gray'), plt.title('灰度圖像')
plt.subplot(122), plt.imshow(texture, cmap='gray'), plt.title('紋理圖像')
plt.show()
# 導入所需的庫
from skimage import io, color, exposure, feature
import matplotlib.pyplot as plt
# 讀取圖像并將其轉換為灰度圖像
image = io.imread('../image/face.jpg')
img = color.rgb2gray(image)
# 提取圖像的局部二值模式特征衫贬,使用不同的方法
texture1 = feature.local_binary_pattern(img, 8, 1.0, method='default')
texture2 = feature.local_binary_pattern(img, 8, 1.0, method='ror')
texture3 = feature.local_binary_pattern(img, 8, 1.0, method='uniform')
# 計算各個特征的直方圖
textureHist1, bins = exposure.histogram(texture1)
textureHist1 = textureHist1 / textureHist1.max()
textureHist2, bins = exposure.histogram(texture2)
textureHist2 = textureHist2 / textureHist2.max()
textureHist3, bins = exposure.histogram(texture3)
textureHist3 = textureHist3 / textureHist3.max()
# 繪制圖像和特征的直方圖
plt.figure(figsize=(6, 7))
plt.subplot(321), plt.imshow(texture1, cmap='gray')
plt.subplot(322), plt.plot(bins, textureHist1)
plt.subplot(323), plt.imshow(texture2, cmap='gray')
plt.subplot(324), plt.plot(bins, textureHist2)
plt.subplot(325), plt.imshow(texture3, cmap='gray')
plt.subplot(326), plt.plot(bins, textureHist3)
plt.show()
第 6 周
import cv2
imgFile="../image/circle.jpg"#讀取文件的路徑
img = cv2.imread(imgFile)
imgGray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) # 彩色轉灰度
t, binary = cv2.threshold(imgGray, 127,255, cv2.THRESH_BINARY) # 二值化
# 檢測圖像中出現(xiàn)的所有輪廓,記錄輪廓的每一個點
contours, hierarchy = cv2.findContours(binary, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)
#繪制所有輪廓歇攻,寬度為5固惯,顏色為紅色
cv2.drawContours(img, contours, -1,(0, 0, 255),3)
cv2.imshow("Demo",img)
cv2.waitKey()
cv2.destroyAllindows()
import cv2
import numpy as np
from skimage import data,color
import cv2
from matplotlib import pyplot as plt
img = cv2.imread('../image/test_img2.jpg')
imgray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(imgray, 127, 255,0)
contours,hierarchy= cv2.findContours(thresh,1,2)
cv2.drawContours(img, contours, -1,(0, 255, 0), 2)
cnt = contours[0]
M= cv2.moments(cnt)
cx = int(M['m10'] / M['m00'])
cy = int(M['m01'] / M['m00'])
print(cx,cy)
plt.imshow(img)
plt.plot(cx,cy,'rs')
plt.show()
import cv2
import numpy as np
from skimage import data,color
import cv2
from matplotlib import pyplot as plt
img = cv2.imread('../image/test_img.jpg')
imgray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(imgray, 127, 255,0)
contours,hierarchy= cv2.findContours(thresh,1,2)
cv2.drawContours(img, contours, -1,(0, 255, 0), 2)
cnt = contours[0]
M= cv2.moments(cnt)
cx = int(M['m10'] / M['m00'])
cy = int(M['m01'] / M['m00'])
area = cv2.contourArea(cnt)
# area = M['m00']
perimeter= cv2.arcLength(cnt,True)
print('面積:', area)
print('周長:', perimeter)
plt.imshow(img, cmap='gray')
plt.plot(cx,cy,'rs')
plt.show()
import cv2
img = cv2.imread('../image/test_img.jpg')
imgray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(imgray, 127,255,0)
contours,hierarchy= cv2.findContours(thresh,1,2)
cv2.drawContours(img,contours,-1,(0,255,0),2)
cnt=contours[0]
#(x,y)為矩形左上角的坐標,(w,h)是矩形的寬和高
x,y,w,h=cv2.boundingRect(cnt)
img = cv2.rectangle(img,(x,y),(x+w,y+h),(0,0,255),2)
cv2.imshow('1', img)
cv2.waitKey()
cv2.destroyAllWindows()
import cv2
import numpy as np
img = cv2.imread('../image/test_img.jpg')
imgray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(imgray, 127,255,0)
contours,hierarchy = cv2.findContours(thresh,1,2)
cv2.drawContours(img, contours, -1,(0, 255, 0), 2)
cnt=contours[0]
rect =cv2.minAreaRect(cnt)#找面積最小的矩形
box=cv2.boxPoints(rect)# 得到最小矩形的坐標
box=np.int0(box)# 標準化坐標到整數(shù)
cv2.drawContours(img, [box],0,(0,0,255),2)#畫出邊界
cv2.imshow('1', img)
cv2.waitKey()
cv2.destroyAllWindows()
import cv2
img = cv2.imread('../image/test_img.jpg')
imgray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(imgray, 127, 255, 0)
contours,hierarchy = cv2.findContours(thresh,1,2)
cv2.drawContours(img,contours,-1,(0,255,0),2)
cnt=contours[0]
(x,y),radius = cv2.minEnclosingCircle(cnt)
center =(int(x),int(y))
radius = int(radius)
img = cv2.circle(img,center,radius,(0,0,255),2)
cv2.imshow('1', img)
cv2.waitKey()
cv2.destroyAllWindows()
import cv2
# reading image
img = cv2.imread('../image/shapes.jpg')
#converting image into grayscale image
gray= cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
# setting threshold of gray image
_, threshold = cv2.threshold(gray, 127,255, cv2.THRESH_BINARY)
# using a findContours() function
contours,_= cv2.findContours(threshold, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
cv2.drawContours(img, contours, -1,(0,0, 255),2)
cv2.imshow('window', img)
cv2.waitKey()
cv2.destroyAllWindows()
import cv2
# reading image
img = cv2.imread('../image/shapes.jpg')
# converting image into grayscale image
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# setting threshold of gray image
_, threshold = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
# using a findContours() function
contours, _ = cv2.findContours(
threshold, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
i = 0
# list for storing names of shapes
for contour in contours:
# here we are ignoring first counter because
# findcontour function detects whole image as shape
if i == 0:
i = 1
continue
# cv2.approxPloyDP() function to approximate the shape
approx = cv2.approxPolyDP(
contour, 0.01 * cv2.arcLength(contour, True), True)
# using drawContours() function
cv2.drawContours(img, [contour], 0, (0, 0, 255), 2)
# finding center point of shape
M = cv2.moments(contour)
if M['m00'] != 0.0:
x = int(M['m10'] / M['m00'])
y = int(M['m01'] / M['m00'])
# putting shape name at center of each shape
if len(approx) == 3:
cv2.putText(img, 'Triangle', (x, y),
cv2.FONT_HERSHEY_SIMPLEX, 0.6, (255, 255, 0), 2)
elif len(approx) == 4:
cv2.putText(img, 'Quadrilateral', (x, y),
cv2.FONT_HERSHEY_SIMPLEX, 0.6, (255, 255, 0), 2)
elif len(approx) == 5:
cv2.putText(img, 'Pentagon', (x, y),
cv2.FONT_HERSHEY_SIMPLEX, 0.6, (255, 255, 0), 2)
elif len(approx) == 6:
cv2.putText(img, 'Hexagon', (x, y),
cv2.FONT_HERSHEY_SIMPLEX, 0.6, (255, 255, 0), 2)
else:
cv2.putText(img, 'circle', (x, y),
cv2.FONT_HERSHEY_SIMPLEX, 0.6, (255, 255, 0), 2)
# displaying the image after drawing contours
cv2.imshow('shapes', img)
cv2.waitKey()
cv2.destroyAllWindows()
import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt
img = cv.imread('../image/bird.jpg')
edges = cv.Canny(img, 10, 50)
edges2= cv.Canny(img, 50, 100)
edges3 = cv.Canny(img, 100, 200)
plt.figure(figsize=(8,8))
plt.subplot(221),plt.imshow(img)
plt.title('Original lmage'), plt.xticks([]), plt.yticks([])
plt.subplot(222),plt.imshow(edges,cmap = 'gray')
plt.title('Edge lmage'), plt.xticks([]), plt.yticks([])
plt.subplot(223),plt.imshow(edges2,cmap = 'gray')
plt.title('Edge lmage'), plt.xticks([]), plt.yticks([])
plt.subplot(224),plt.imshow(edges3,cmap = 'gray')
plt.title('Edge lmage'), plt.xticks([]), plt.yticks([])
plt.show()
第 7 周
import cv2
import numpy as np
img = cv2.imread("../image/bird.jpg")
imgray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 二值化處理
_, imgBinary = cv2.threshold(imgray, 127, 255, cv2.THRESH_BINARY)
# 定義一個5x5的卷積核
kernel = np.ones((5, 5), np.uint8)
# 對二值化圖像進行腐蝕操作
erosion = cv2.erode(imgBinary, kernel)
# 顯示原始圖像缴守、二值化圖像和腐蝕后的圖像
cv2.imshow('Original Image', img)
cv2.imshow('Binary Image', imgBinary)
cv2.imshow('Eroded Image', erosion)
# 等待按鍵葬毫,然后關閉所有窗口
cv2.waitKey()
cv2.destroyAllWindows()
import cv2
import numpy as np
img = cv2.imread('../image/bird.jpg')
imgray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, imgBinary = cv2.threshold(imgray, 127, 255, cv2.THRESH_BINARY)
kernel = np.ones((9, 9), np.uint8)
erosion = cv2.erode(imgBinary, kernel)
erosion2 = cv2.dilate(imgBinary, kernel)
erosion3 = erosion2 - erosion
cv2.imshow('fig1', erosion)
cv2.imshow('fig2', erosion2)
cv2.imshow('fig3', erosion3)
cv2.waitKey(0)
cv2.destroyAllWindows()
import cv2
img = cv2.imread('../image/bird.jpg')
imgray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
gaussian =cv2.GaussianBlur(imgray,(3,3),0,0, cv2.BORDER_DEFAULT)
median =cv2.medianBlur(gaussian,5)
sobel =cv2.Sobel(median,cv2.CV_8U,1,0,ksize=3)
ret, binary = cv2.threshold(sobel,170,255,cv2.THRESH_BINARY)
cv2.imshow('window',binary)
cv2.waitKey()
cv2.destroyAllwindows()
import cv2
import numpy as np
def GetRegion(img):
regions = []
# 尋找輪廓
contours, hierarchy = cv2.findContours(img, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
for contour in contours:
area = cv2.contourArea(contour)
if area < 2000:
continue
# 近似輪廓以減少點的數(shù)量
eps = 0.1 * cv2.arcLength(contour, True)
approx = cv2.approxPolyDP(contour, eps, True)
# 獲取最小外接矩形
rect = cv2.minAreaRect(contour)
box = cv2.boxPoints(rect)
box = np.int0(box)
height = abs(box[0][1] - box[2][1])
width = abs(box[0][0] - box[2][0])
# 計算寬高比
ratio = float(width) / float(height)
# 檢查寬高比是否在一定范圍內(nèi)
if 1.8 < ratio < 5:
regions.append(box)
return regions
img = cv2.imread('../image/bird.jpg')
imgray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 進行膨脹操作
prc = cv2.dilate(imgray, None, iterations=2)
# 獲取感興趣區(qū)域
regions = GetRegion(prc)
# 在原始圖像上顯示感興趣的區(qū)域(矩形框)
for box in regions:
cv2.drawContours(img, [box], 0, (0, 255, 0), 2)
# 顯示帶有感興趣區(qū)域的圖像
cv2.imshow('window', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
第 8 周
import cv2 # 導入 OpenCV 庫
import numpy as np # 導入 NumPy 庫
# 讀取待檢測物體圖像和模板圖像
img = cv2.imread("../image/face.jpg") # 讀取待檢測物體圖像
template = cv2.imread("../image/eyes.jpg") # 讀取模板圖像
# 獲取模板圖像的寬度和高度
w, h = template.shape[:2][::-1]
# 在待檢測物體圖像中進行模板匹配
res = cv2.matchTemplate(img, template, cv2.TM_CCOEFF_NORMED)
# 設定匹配閾值
threshold = 0.9
# 尋找匹配結果中大于等于閾值的位置
loc = np.where(res >= threshold)
# 遍歷所有匹配的位置,并在待檢測物體圖像中繪制矩形框
for i in zip(*loc[::-1]):
cv2.rectangle(img, i, (i[0] + w, i[1]+ h), (0,0,255), 1)
# 顯示模板圖像和帶有檢測結果的待檢測物體圖像
cv2.imshow('template', template) # 顯示模板圖像
cv2.imshow('img', img) # 顯示帶有檢測結果的待檢測物體圖像
# 等待按鍵屡穗,并關閉所有圖像窗口
cv2.waitKey(0)
cv2.destroyAllWindows()
from PIL import Image
# from skimage import io
# img = io.imread('images-D9/lena.jpg')
img = Image.open('images-D9/lena.jpg')
img2 = img.rotate(45) # 逆時針旋轉45
img2.save("lena_rot45.jpg")
img2.show()
"""
圖像匹配——SIFT點特征匹配實現(xiàn)步驟:
(1)讀取圖像贴捡;
(2)定義sift算子;
(3)通過sift算子對需要匹配的圖像進行特征點獲却迳啊烂斋;
a.可獲取各匹配圖像經(jīng)過sift算子的特征點數(shù)目
(4)可視化特征點(在原圖中標記為圓圈);
a.為方便觀察,可將匹配圖像橫向排列
(5)圖像匹配(特征點匹配)汛骂;
a.通過調(diào)整ratio獲取需要進行圖像匹配的特征點數(shù)量(ratio值越大罕模,匹配的線條越密集,但錯誤匹配點也會增多)
b.通過索引ratio選擇固定的特征點進行圖像匹配
(6)將待匹配圖像通過旋轉帘瞭、變換等方式將其與目標圖像對齊
"""
import cv2 # opencv版本需為3.4.2.16
import numpy as np # 矩陣運算庫
import time # 時間庫
original_lena = cv2.imread('lena.jpg') # 讀取lena原圖
lena_rot45 = cv2.imread('lena_rot45.jpg') # 讀取lena旋轉45圖
sift = cv2.xfeatures2d.SIFT_create(100)
# 獲取各個圖像的特征點及sift特征向量
# 返回值kp包含sift特征的方向淑掌、位置、大小等信息蝶念;des的shape為(sift_num抛腕, 128), sift_num表示圖像檢測到的sift特征數(shù)量
(kp1, des1) = sift.detectAndCompute(original_lena, None)
(kp2, des2) = sift.detectAndCompute(lena_rot45, None)
# 特征點數(shù)目顯示
print("=========================================")
print("=========================================")
print('lena 原圖 特征點數(shù)目:', des1.shape[0])
print('lena 旋轉圖 特征點數(shù)目:', des2.shape[0])
print("=========================================")
print("=========================================")
# 舉例說明kp中的參數(shù)信息
for i in range(2):
print("關鍵點", i)
print("數(shù)據(jù)類型:", type(kp1[i]))
print("關鍵點坐標:", kp1[i].pt)
print("鄰域直徑:", kp1[i].size)
print("方向:", kp1[i].angle)
print("所在的圖像金字塔的組:", kp1[i].octave)
print("=========================================")
print("=========================================")
"""
首先對原圖和旋轉圖進行特征匹配祸轮,即圖original_lena和圖lena_rot45
"""
# 繪制特征點,并顯示為紅色圓圈
sift_original_lena = cv2.drawKeypoints(original_lena, kp1, original_lena, color=(0, 255, 0))
sift_lena_rot45 = cv2.drawKeypoints(lena_rot45, kp2, lena_rot45, color=(0, 255, 0))
sift_cat1 = np.hstack((sift_original_lena, sift_lena_rot45)) # 對提取特征點后的圖像進行橫向拼接
cv2.imwrite("sift_cat1.png", sift_cat1)
print('原圖與旋轉圖 特征點繪制圖像已保存')
cv2.imshow("sift_point1", sift_cat1)
cv2.waitKey()
# 特征點匹配
# K近鄰算法求取在空間中距離最近的K個數(shù)據(jù)點侥钳,并將這些數(shù)據(jù)點歸為一類
start = time.time() # 計算匹配點匹配時間
bf = cv2.BFMatcher()
matches1 = bf.knnMatch(des1, des2, k=2)
print('用于 原圖和旋轉圖 圖像匹配的所有特征點數(shù)目:', len(matches1))
# 調(diào)整ratio
# ratio=0.4:對于準確度要求高的匹配适袜;
# ratio=0.6:對于匹配點數(shù)目要求比較多的匹配;
# ratio=0.5:一般情況下舷夺。
ratio1 = 0.5
good1 = []
for m1, n1 in matches1:
# 如果最接近和次接近的比值大于一個既定的值苦酱,那么我們保留這個最接近的值,認為它和其匹配的點為good_match
if m1.distance < ratio1 * n1.distance:
good1.append([m1])
end = time.time()
print("匹配點匹配運行時間:%.4f秒" % (end - start))
# 通過對good值進行索引给猾,可以指定固定數(shù)目的特征點進行匹配疫萤,如good[:20]表示對前20個特征點進行匹配
match_result1 = cv2.drawMatchesKnn(original_lena, kp1, lena_rot45, kp2, good1[:20], None, flags=2)
cv2.imwrite("match_result1.png", match_result1)
print('原圖與旋轉圖 特征點匹配圖像已保存')
print("=========================================")
print("=========================================")
print("原圖與旋轉圖匹配對的數(shù)目:", len(good1))
for i in range(2):
print("匹配", i)
print("數(shù)據(jù)類型:", type(good1[i][0]))
print("描述符之間的距離:", good1[i][0].distance)
print("查詢圖像中描述符的索引:", good1[i][0].queryIdx)
print("目標圖像中描述符的索引:", good1[i][0].trainIdx)
print("=========================================")
print("=========================================")
cv2.imshow("original_lena and lena_rot45 feature matching result", match_result1)
cv2.waitKey()
# 將待匹配圖像通過旋轉、變換等方式將其與目標圖像對齊敢伸,這里使用單應性矩陣扯饶。
# 單應性矩陣有八個參數(shù),如果要解這八個參數(shù)的話池颈,需要八個方程尾序,由于每一個對應的像素點可以產(chǎn)生2個方程(x一個,y一個)躯砰,那么總共只需要四個像素點就能解出這個單應性矩陣每币。
if len(good1) > 4:
ptsA = np.float32([kp1[m[0].queryIdx].pt for m in good1]).reshape(-1, 1, 2)
ptsB = np.float32([kp2[m[0].trainIdx].pt for m in good1]).reshape(-1, 1, 2)
ransacReprojThreshold = 4
# RANSAC算法選擇其中最優(yōu)的四個點
H, status = cv2.findHomography(ptsA, ptsB, cv2.RANSAC, ransacReprojThreshold)
imgout = cv2.warpPerspective(lena_rot45, H, (original_lena.shape[1], original_lena.shape[0]),
flags=cv2.INTER_LINEAR + cv2.WARP_INVERSE_MAP)
cv2.imwrite("imgout.png", imgout)
cv2.imshow("lena_rot45's result after transformation", imgout)
cv2.waitKey()
import cv2
import numpy as np
def sift_kp(image):
gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
sift = cv2.xfeatures2d.SIFT_create(100)
#SIFT算子實例化
kp, des = sift.detectAndCompute(image, None)
# sift.detectAndComputer(gray, None)
# 計算出圖像的關鍵點和sift特征向量
kp_image = cv2.drawKeypoints(gray_image, kp, None)
#ret = cv2.drawKeypoints(gray, kp, img) 在圖中畫出關鍵點
#參數(shù)說明:gray表示輸入圖片, kp表示關鍵點琢歇,img表示輸出的圖片
return kp_image, kp, des
def get_good_match(des1, des2):
bf = cv2.BFMatcher()
#對兩個匹配選擇最佳的匹配
matches = bf.knnMatch(des1, des2, k=2)
# des1為模板圖兰怠,des2為匹配圖
matches = sorted(matches, key=lambda x: x[0].distance / x[1].distance)
good = []
for m, n in matches:
if m.distance < 0.75 * n.distance:
good.append(m)
return good
img1 = cv2.imread('lena.jpg')
img2 = cv2.imread('lena_rot45.jpg')
kpimg1, kp1, des1 = sift_kp(img1)
kpimg2, kp2, des2 = sift_kp(img2)
print('descriptor1:', des1.shape, 'descriptor2', des2.shape)
#輸出特征點(描述子)的維度
cv2.imshow('img1',np.hstack((img1,kpimg1)))
cv2.waitKey()
cv2.imshow('img2',np.hstack((img2,kpimg2)))
cv2.waitKey()
goodMatch = get_good_match(des1, des2)
all_goodmatch_img= cv2.drawMatches(img1, kp1, img2, kp2, goodMatch, None, flags=2)
#drawMatches(圖1,圖1特征點李茫,圖2揭保,圖2特征點,圖1的特征點匹配圖2的特征點(所有)魄宏,顏色都是默認掖举,flags表示有幾個圖像)
# goodmatch_img自己設置前多少個goodMatch[:50]
goodmatch_img = cv2.drawMatches(img1, kp1, img2, kp2, goodMatch[:10], None, flags=2)
cv2.imshow('all_goodmatch_img', all_goodmatch_img)
cv2.waitKey()
cv2.imshow('goodmatch_img', goodmatch_img)
cv2.waitKey(0)
cv2.destroyAllWindows()
import cv2
import numpy as np
def cv_show(name, image):
cv2.imshow(name, image)
cv2.waitKey(0)
cv2.destroyAllWindows()
def detectAndCompute(image):
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
sift = cv2.xfeatures2d.SIFT_create(500)
(kps, features) = sift.detectAndCompute(image, None)
kps = np.float32([kp.pt for kp in kps]) # 得到的點需要進一步轉換才能使用
return (kps, features)
def matchKeyPoints(kpsA, kpsB, featuresA, featuresB, ratio = 0.5, reprojThresh = 4.0):
# ratio是最近鄰匹配的推薦閾值
# reprojThresh是隨機取樣一致性的推薦閾值
matcher = cv2.BFMatcher()
rawMatches = matcher.knnMatch(featuresA, featuresB, 2)
matches = []
for m in rawMatches:
if len(m) == 2 and m[0].distance < ratio * m[1].distance:
matches.append((m[0].queryIdx, m[0].trainIdx))
kpsA = np.float32([kpsA[m[0]] for m in matches]) # 使用np.float32轉化列表
kpsB = np.float32([kpsB[m[1]] for m in matches])
(M, status) = cv2.findHomography(kpsA, kpsB, cv2.RANSAC, reprojThresh)
return (M, matches, status) # 并不是所有的點都有匹配解,它們的狀態(tài)存在status中
def stich(imgA, imgB, M):
result = cv2.warpPerspective(imgA, M, (imgA.shape[1] + imgB.shape[1], imgA.shape[0]))
result[0:imageA.shape[0], 0:imageB.shape[1]] = imageB
cv_show('result', result)
def drawMatches(imgA, imgB, kpsA, kpsB, matches, status):
(hA, wA) = imgA.shape[0:2]
(hB, wB) = imgB.shape[0:2]
# 注意這里的3通道和uint8類型
drawImg = np.zeros((max(hA, hB), wA + wB, 3), 'uint8')
drawImg[0:hB, 0:wB] = imageB
drawImg[0:hA, wB:] = imageA
for ((queryIdx, trainIdx),s) in zip(matches, status):
if s == 1:
# 注意將float32 --> int
pt1 = (int(kpsB[trainIdx][0]), int(kpsB[trainIdx][1]))
pt2 = (int(kpsA[trainIdx][0]) + wB, int(kpsA[trainIdx][1]))
cv2.line(drawImg, pt1, pt2, (0, 0, 255))
cv_show("drawImg", drawImg)
# 讀取圖像
imageA = cv2.imread('sztu2.jpg')
imageA = cv2.resize(imageA,(540,398))
cv_show("imageA", imageA)
imageB = cv2.imread('sztu1.jpg')
imageB = cv2.resize(imageB,(540,398))
cv_show("imageB", imageB)
# 計算SIFT特征點和特征向量
(kpsA, featuresA) = detectAndCompute(imageA)
(kpsB, featuresB) = detectAndCompute(imageB)
# 基于最近鄰和隨機取樣一致性得到一個單應性矩陣
(M, matches, status) = matchKeyPoints(kpsA, kpsB, featuresA, featuresB)
# 繪制匹配結果
drawMatches(imageA, imageB, kpsA, kpsB, matches, status)
# 拼接
stich(imageA, imageB, M)
import cv2
target = cv2.imread('image/lena.jpg')
img = cv2.cvtColor(target, cv2.COLOR_BGR2GRAY)
template = cv2.imread('image/lena_face.jpg')
h, w= template.shape[:2]
# 相關系數(shù)匹配方法: cv2.TM_CCOEFF
result = cv2.matchTemplate(target, template, cv2.TM_CCOEFF_NORMED)
min_val, max_val, min_loc, max_loc=cv2.minMaxLoc(result)
left_top=max_loc #左上角
right_bottom=(left_top[0]+w, left_top[1]+h)#右下角
cv2.rectangle(target, left_top, right_bottom,(0,0,255),2)#畫出矩形位置
cv2.imshow('temp', template)
cv2.imshow('result', target)
cv2.waitKey(0)