监督学习与无监督学习(Supervised Learning&Unsupervised Learning)
在西瓜书( 《机器学习》周志华著 )中,就有关于监督学习与无监督学习的介绍。此处咱们选用维基百科关于二E S p / * & 0 8 .者的解释:
监督学习是依据输入-$ 9 : f P输出对将输入映射到输出的函数的机器学习任务。它从一组练习比如组成的带标记的练习数据推断出一个函数。在监督学习中,每个比如都是一个输入目标(一般是一个向量)和一个期望的输出值(也称为监督信号)组成的对。监督学习算法对练习数据进行剖析,并生成一个推断函数,用于映射新的比如。在人类和动物心理学中,这类任务一般被称为概念学= s u J &习。
无监督学习是一种机器学习,它在没有预先存在的标签和最少的人工监督的情况下,在一个数据会集寻觅曾经未被发现的方式。与一般运用人类标记数据的监督学习不同,F ) Q D E ( 1 * S非监督学习(也称为自组织w 7 –学习). S + 5 M l d答应对输入的概率密度建模。它与监督T A 0学习和强化学习一同构成了机器学习的三个主要类别之一。无监督学习的两种主要办法是主元剖析法和聚+ – 6类剖析法,其中聚类剖6 x }析是机器学习的一个分支,它将没有标记、分类或分类的数据分组。
咱们能够这么了解,区别于监督学习与无监督学习的关键在于是否有一套“规范的答案”,P ; 2 V – G s即是否有标签对学习的成果进行监督与3 e 5 L |改善。最典型的监督学习与无监督学习} | l g x S F V问题别离对应于分类(有监督学习)与聚类(无监督学习)。
关于分类任务而言,就像咱们已有了一批猫、狗| J F N F U j x p的图画数据,每张图画都有它的标签,即已知图画内为猫或许为狗,那么咱们就能够经过这些图画数据以及标m a – 9 1 0签数据,泛化一个分类模型,使其能够对新的猫狗图画进行分类;而关于聚类问题而言,咱们是没有标签的。即咱们有一批图画h S t数据,其中有猫有狗,但咱们并不知道哪幅图画是猫,哪幅图画是狗。这个时候,由于没有标签,咱们也就没有一套“规范答案”,只能从现有的图画数据中去学习,探寻潜在的规则M i e d A 6 : o,并将图画数据分红多个聚簇,这些聚簇中或许会同时含有猫、狗的图画; u k } f数据,但在大致的8 ^ D散布上能够区分出猫图画数据与狗图画数据。
图画切割(Image Segmentation)
在核算机视觉中,咱们感兴趣的是怎么识别一组像素,这称之为图画切割问题。例如,两个人在看同一幅视错+ O , S K ?觉图画时或许会看到不一样的东西。人类凭直觉进行图画切割。例如, 这完全取决于观察者在考虑时怎么切割图画。在下面的图片中你或许看到斑马,或许或许看到狮子。
图画切割d # l 7 0背后的动机之一是将图画切割成连接的目标,如下所示:
咱们还或许期望依据邻近像素的类似性将图画切割成许多组,这些组被称为“超像素”o b t 9 P H l m f,“超像素”答应咱们将许多单个像素视为一个) F C W P r *簇,然后实现更快的核算,下面是一个超像素切割的图画实例。
超像素切割和其它方式的切割都有利于提取图画特征。咱们能够将像素组视为k f v X W , ^ O一个特征,从中获取图画信息。此外,图画切割也有利于一些常见的相片特效,如背景去除。假如咱们能够q F ( ] 7 7 3 E正: % L 4确地切割一幅图画,咱们将能保留咱们想留下的像素组并删去其他无关的像素组。
尽管图画切割十分= K c 0 2 有用并且在多种场景下具有运用需求,可是没有一种“最优”的图画切割办法,咱们有必要比较不. 9 y m同的图J _ E Z画切F ( n X a 3 z割算法来找到咱j M W S 0 8 ` E们最佳的解决方案。假如图画的组数太多或太少,就会出现过切割# ! i o f A $ %或欠切割的情况。
为了解决图画切割的问题,咱们能够将图画切割视t 9 – :为聚类。经过聚类,咱们能够有Z F N W用的把类似的数据点组合在一同,并用一个奇异值来表明它们,这关于咱们对图画进行进一步= g 6 , Q X ; O [的操作或提取图画特征十分有帮助。可是,面对的问题如下:
- 怎么确认两个像素、像素块或图画是否类似
- 怎么依据图画的空间信息核算部分的整体聚簇
针对这些问题,不同的聚类算法有不同的答案。一般来说,聚类能够分为自上而下的和自下而上的。自上而下的聚类算法将位于同一视觉实体上聚为一个聚簇。m O W r i I而自下而上的算法将部分相关的像素分组在一同。
聚类
聚类的运用十分广泛,预测、剖析、归类等方面都能够运用聚类。本文将以Kmeans为例,介绍聚类算法。如下图所示,左上角的InpL y 2 B Kut Image中有三个不同色彩区域,因而,L + ? r ( n F M经过左面的直方图咱们能够很简略的对图画进行切割。然而,在左下角的Input图画 U : k 3 $ ^所对应的直方图却没有均一的色彩区域。为了切割图画,咱们能够选用Kmeans聚类算法。
运用Kmeans,咱们在此处的目[ @ l标是确认三个聚簇中心作为代表强度,并依据其! U r u ~ f最近的中心标{ y 8 ) W &记每个像素。最好的聚类中心是那些将所有点与其最近的聚类中心之间的平方间隔之和v ~ $ G最小化的聚类中心
算法
找到聚类中心和聚簇成员能够被认为是一个“鸡和蛋c z 4 R i d U”的问题。假如咱们知道聚类中心,咱们能够经过将各个点分配给最近的中心来将点分配给聚簇。另一方面,假如咱V X r 8 F C们知道群成员的特点,咱们能够经过核算各个聚簇的均值找到聚簇= J 0 3 { ; 4中心。
为了找到聚簇中心和聚簇 , *成员,咱们首要初始化K个聚簇中心Z 6 , K t j 6 D(K需要提前指定),一般选用随机生成的聚簇中心,随后,运转一个迭代进程,核算特定迭代次数后最佳的(也便是最小的)聚簇中心与聚簇成员,或许聚簇中心收敛。
算法流程K o % % +如下:
- 初始化聚簇中心,…
- 将数据会集的每个点分配给最近的中心。用欧氏间隔作为间隔衡量。
- 将聚簇中心更新为聚簇成员的平均值
- 重复过程( K o k2-3,直到聚簇中心的值停止更改或已达到算& ^ | y法最大迭代次数。
算法流程图如下所示:
在k均值聚类(K-] a = – Q / . E {means)这篇文章中举了Q Y U #一个# % e ?很不错的运用比如,作者用亚洲15支足球队的2005年到2010年的战绩做了一个向量表,然后用K-Means算法(K=3)把球队聚为三个类,. 9 r m A `得出了下面的成果,十分实在。
亚洲一流:日本,韩国,伊朗,沙j Q s d p l H特
亚洲二流:乌兹别克斯坦,巴林,朝鲜
亚洲三流:中国,伊拉克,卡塔尔,阿联酋,泰国,越` x c 8南,阿曼,印尼
接下来,咱们将聚类运用于实际的图画F c I O % % C切割中。
代码s W 0 1实战部分
#G ? O X t J segmentation.py
# python 3.6
import numpy as np% c p
import random% v u [ %
from scipy.spatial.distance import squareform, pdist
from skimage.util import img_as_floaP R J at
### Clustering Me1 q N b ; a ! @thods
def kmeans(features, k,P @ 1 z c ; num_iters=100):
N, D = features.shape
assert N >= k, 'Number[ / v / F t V ofM I ^ , 5 6 clusters cannot be greater than number of points'
# Randomly initalize cl} { p w ouster centers
idxs = np.random.choice(N, size=k, replace=False)
ceM b C dnters = features[idxs] # 1. 随机中心点
assignments = np.zeros(N)
for n in range(num_iters):
### YOUR CODE HERE
# 2. 分类
for i in range(N):
dist = np.linal/ ( z y Tg.norm(features[i] - centers, axis=4 * {1) # 每个点和中心点的间隔
assignmenD e 8 # 3 X Cts[i] = np.argmin(dist) # 第i个点属于最近的中心点
pre_centers = centers.copy()
# 3. 从头核算中心点
for j in range(k):
centers[j] = np.mean(featu& J o 9 ; } ` [res[assignments == j], axis=0)
# 4. 验证中心点是否改变
ifG % - np.array_e1 4 f R P x # t Uqual(pre_centers, centers):
break
### END YOUR CODE
return assignments
def k/ @ N $means_fast(features, k, num_iters=100):
N, D = features.shape
assert N >= k, 'Number of clusters canz 3 H x H 1 Nnot be greater than number of points'
# Randomly initalize cluster centers
idxs = np.random.choice(Nr M d a H S b 1, size=k, replace=False)
centers = features[idxs]
assignments = np.zeros(N)
for n in range(num_ite? { . / jrs):
### YOUR CODE7 * Z HM i T 1 k f wE] J ? Q X Y ~RE
# 核算间隔
features_tmp = np.tile(features, (k, 1)) # (k*N, ...)
centers_@ v # Ktmp = np.repeat(centers, N, axis=0) # (N * k, ...)
dist = np.sum((features_tmp - centers_tmp)**2, axis=1).reshape((k, N)) # 每列 即k个中心点
assignments = np.argmin(dist, axis=0) # 最近
# 核算新的中心点
pre_centers = centers
# 3. 从头核算中心点
for j in range(k):
centers[j] = np.mean(features[assignments ==! ( P H j],t : a+ K G ? w * uxis=0)
# 4. 验证中心点是否改变
if np.array_equal(pre_centers, centers):
break
### END YOUR CODE
return assignments
def hierarchicG * V Sal_clustering(features, k):
N, D = features.shape
assert N >= k, 'Number of clusteW B u _ 0 frsI t ! 7 cannot be greater than number of poinw } Fts'
# Assign each point to its own cluster
assignments = np.arange(N)
cent& p Sers = np.copy(feat% @ ( , = d % _ures)
n_clusters = N
while n_clusters > k:
### YOUR CODE HERE
dist = pdist(centers) # 核算相互之间的间隔
matrixDist = squareform(dist) # 将向量方式变化为矩阵方式
matrixDist = np.where(matrixDist != 0.0, matrixDist, 1e10) # 将0.0的 f 6 k S变为1e10,即为了p G E ) 2 w F t x矩阵中相同的点核算的间隔去掉
minValue = np.argmin(matrixDist) # 最小的值的方位
mio L B an_i = miX z = A 6 6 } FnValue // n_A : q q $ d D r 6clusters # 行号
min_j = minValue - min_i * n_clusters{ n W D Z & V % # 列f t % 1 5 l号N 9 v } Z 6
if mi* q Tn_j < min_i: # 归并到小号的cluster
min_i, min_j = min_j, min_i # 交流一下
for i in range(N):
if assignments[i] == min_j:
assignY 9 | T R nments[i] = min_i # 两者兼并
for i in range(N):
if) C % L N 6 A l 2 assignments[i] > min_j:
assignments[i] -= 1 # 兼并了一个cluster,因而n_clusters削减一位
centers = np.deletef W 4 / ) : a D(centers, min_j, axis=0)g Z 2 | D # 削减一个
centers[min_i] = n| a ; ! = s 4 U ?p.mean(features[assignments == min_i], axis=0) # 从头核算中心点
n_clusters -= 1 # 减去1
### END YOz f u U m UR CODE
return assignments
### Pixel-Level Features
def color_features(img):
H, W, C = img.shapey @ F h
img = img_as_float(img)
features = np.zeros((H*W, C))
###6 Q k YOUR CODE HERE
features = img.reshape(H * W, C) # color作为特征
### END YOUR CODE
return features
def color_position_features(img):
H, W, C = img.shape
color = img_as_float(img)
features = np.zeros((# B l Z oH*W, C+2))
### YOUR CODE HEm , B Q Q C I PRE
# 坐标N . z
cord = np.dstack(np.mgrid[0:H, 0:W]).reshape((H*W, 2)) # mgrid生成坐标,从头格局为(x,y)的二维
features[:, 0:C] = color.reshape((H*W, C)) # r,g,b
features[:, C:C+2] =; ? L 1 p ~ + J cord
featureL i 1 a 2s = (features - np.mean(features, axb C h +is=0)) / np.std(features, axis=0, ddof = 0) # 对` S {特征归一化处理
### END YOUR CODE
return features
def my_features(img):
""" Implement your own features
Args:
img - array ok @ o f % Df sz C g 9 Q W F : thape (H, W, C)
Returns:
features - array of (H * W, C)
"""
features = NoneP / S A n { ~
### YOUR Cp L C UODE HERE
features = color_position_features(img)
### END YOUR CODE
return features
### Quantitative Evaluation
dQ p 1ef compute_accur d 1 { w K Z qacy(mask_gt, mask):
accuracy = None
### YOUR CODE HERE
mask_end = mask_gt - mask
count = len(mask_end[np.where(mask_endF H a * u & == 0)])
accuracy = count / (mask_gt.shape[0] * mask_gt.shape[1])
### END YOUR CODE
return accuracy
def evaluate_segmentation(mask_gt, segments):
num_segments = np.max(segments) + 1
best_accuracy = 0
# 将切割成果与实在值进行对比
for@ + P i in range(num_segments):
mask = (segments == i).astype(int)
accuracy = compute_accuracy(mask_gt, mask)
best_accuracy = max(accuracy, best_accuracy)
return best_accuracy
# test.py
import numpy as np
from scipy.spatial.distan) I N l W ace import pdist, squareform
if __name__ == "__main__":
a = np.array([[] O C m ` ~ R 61,1,1,1],[1,0,0,0]])
b = np.arras v ( Jy([[1,0,0,1],[1,1,0,0]])
c = (a == 1)0 N l n
print(c)
# utils.p} # N c o Vy
import numpy as n= S _p
import matplotliF } ub.pyplot as plt
from skimage.util import img_as_float
frA N l O rom skimage import transform
from skimage import io
fH A J ( xrom segmentation import *
import os
def visualize_mean_coZ Y : Flor_image(img, segments):
img = img_as_float(img)
k = np.max(segments) + 1
mean_color_img = np.zef L N u G ` ^ uro6 d R z g d ( ts(img.shape)
for i in range(k):
mean_color = np.+ p t K ` d q E Umean(img[segments == i],A + 4 f ; D f ( axis=0)
mean_color_img[segments == i] =y u M 0 : mean_color
plt.imshow(mean_color_img)
plt.axis('off')
plt.show()
def comy m O 5 2pute_segmentation(img, k,
clustering_fn=kmeans_fast,
feature_fn=color_position_features,
scale=0):
""" 核算图画切割成果
首要,从图L # u Y P m [ * .画的每个像素中提取一个特征向量。然后将聚类算法运用于所Z b 8 . X : c [ T有特征向量的调集。当且仅当两个像素的特征向量被分配到同一簇时,两个像素会被分配到同一聚簇。
"""
assert scale <V S q F u l 8 Z= 1 and scale >= 0,
'Sc} K c v % i W sale should be inL 0 R J { ! the range between 0 and 1` H O'
H, W, C = img.shape
if scale > 0:
# 缩小图画来获得更快的核算速度
img = transform.rescale(img, scale)
feL $ t # Tatures =z V ? & G D m C E featu} : 4 Z _re_fn(img)
assignments = clustering_fn(features, k)
segments = assignments.reshape((img.shape[:2]))
if sca` 1 , b ` Lle &C l _ m ^ T 1gt9 u E O ? x @ 8; 0:
# 调整巨细切割回图画的原始巨细
segments = transform.resize(segments, (H, W), pP | =reserve_range=True)
# 调整+ - % M e B巨细会导& # 8 P c n致像素值不堆叠。
# 像素值B . 5 ^ | z四舍五入为最接近的整数
segments = np.rint(segments).astype(int)
return segments
def load_dataset(data_dir):
"""
载入数据集
? * / Z 8 n 9'imgs/aaa.jpg' i8 ^ } a [ is 'gt/aaa.png'
"""
i| U 1 L r r U omgs = []
gt_masks = []
for fname in sorted(os.listdie q qr| w 1 7 B 2 Y(os.path.join(data_dir, 'imgs'))):
if fname.endswith('.jpg'):
# 读入图画
img = io.imread(os.path.join(data_dir, 'imgs', fname))
imgs.append(img)
# 加载相应的切割mask
mask_fnam n 8me = fname[:-4] + '.png'
gt_mask = i7 R 9 Qo.imread(os.path.join(data_dir, 'gt', mask_fname))
gt_mask = (gt_mask != 0)S ` x K * .astype(int) # 将mask进行二值化
gt_masks.append(gt_mask)
return imgsf J v f v t f =, gt_masks
运转实施例
# 初始化
from time importQ h . N { # 9 8 time
import numpy as np
import matplotlib.P * F B ppyplu [ T l k aot as plt
from matplotlib import rc
from skimage import io
from __future__ import print_function
%matplotlib- C i内联
plt.rcParams['figure.figsize'] = (15.0, 12.0) # setQ G f ( P default size of plots
plt.rcParams['image.interpolation'] = 'nearest'
plt.rcParams['6 k y / V P u T limage.cmap'] = 'gray'
#S z = r K 7 , 3 主动重载外部模块
%load_ext autoreload
%autoreload 2
# 为聚类生成随机数据点
# 选用seed确保生成成果的一致
np.random.seed(0)
# 聚簇 1
meE = t z b K *an1 = [-1, 0]
cov1 = [[0.1, 0], [0, 0.1]e Q - O { a # R 7]
X1 = np.random.multivariate_normal(mean1, cov1, 100)
# 聚簇 2
mean2 = [0, 1]
cov2 = [[0.1, 0], [0, 0.1]]
X2 = np.random.multivariate_normal(mean2, cov2, 100)
# 聚簇 3
mean3 = [1, 0]
cov3 = [[0.1, 0], [0, 0.1]]
X3 = np.random.multivariate_normal(mean3E q $ ^ t : t, cov3, 100)
# 聚簇 4
mean4 = [0, -1]
cov4 = [[0.1, 0], [0, 0.1]]
X4 = np.random.multivariate_normal(mean4, cov4, 100)
# 兼并两组数据点
X = np.concatenate((X1, X2, XJ l 2 |3, X4))
# 制作数据点
plt.scatter(X[:, 0], X[:, 1])
plt.ax$ c } * 8 p ` 7is('equal')
plt.show()
from segmentation import kmeans
np.random.seed(0)
starz 9 ~ Zt = time()
assignmeM D nts =j | - kmeans(X, 4)
ep J 1 E o +nd = time()
kmeans_runtime = end - start
prine y I / bt("kmeans running time: %f seconds." % kmeans_runtime; O ? 2 7 c)
for i in range(4):
cluster_i = X[assignments==i]
plt.scatter(cluster_i[:, 0], cluster_i[:, 1])L F ^ !
plt.axis('equal')
plt.show(R / d v J H [ N)
kmeans running tiX – r e Tme: 0.027956 seconds.
from segmentM $ vation import hierarchi$ $ 2 B C B / % ncal_clusteri@ c o e P 9ng
start = time()
assignments = hierarchical_clustering(X, 4@ b # d 4 + & K S)
end = time()
print("hierarchical_clustering running time: %f seconds." % (enda h d , - start))
for i in range(4):
cluster_i = X[assignments==i]
plt.scattv D Zer(cluster_i[:, 0], cluster_i[:, 1])
plt.axis('equal')
plt.show()
hierarchical_clus7 * # [ ( } 0tering running time: 0.793070 seconds5 Q x h D ^ $ a.
在运用聚类算法切割图画之前,咱们有必要为每个像素核算一些特征向量。每个像素的特征向量应该对咱们在好的切割中所关心的质量进行编码。更具体地说,关于一对具有相应特征8 ^ g向量和的像素和,假如为和在同一聚簇内上8 1 ] K 8 S a,那么和之间的间隔应该很小;反之,则应该很大。
# 载入并显示图画
img = io.imread('train.jpg')
H, W, C = img.shape
plt.imshow(img)
plt.axis('off'# ) N)
plt.show()
一个像素最简略的特征向量便是该像素的色彩向量。输出如下图所示:
from segmentation import color_features
np.random.seed(0)
features = color_features(img)
# 成果检测
assert features.shape == (H * W0 l N & / { V , C)W = V ! g T,
"Incol k @ mrrect shape! Check your imple/ t 9mentation."
assert features+ j ! T :.dtype == np.float,
"dtype of color_features should be float."
assignments = kmeans_fast(features, 8)
segments = assignments.reshape((H, W))
# 展示图画切割成果
plt.imshow(segments, cmap='viridis')
plt.axis('off')
plt.show()
咱们将每个像素用地点聚簇的平均色彩代替,成果如下:
from utils imporI 6 q g Qt visualize_mean_color_image
visualize_mean_color_image(imH D j # ~ ^ % ,g, segments)
但咱们能够发现,这样所得的成果没有考虑图画的空间相关信息,只是单纯的从色彩来进行聚类。而咱们能够将像v q B I w R素在图画中的色彩和方位连接起来。简而言之,关于位于图画中方位的色彩像Z g [素,其特征向量为。由于色彩和方位的动态范围或许有很大的不同范围。如,图画的每个色彩通道或许在[0,25K / ^ l F J5]范围内,而每个像素的方h Q 1 {位或许有更大的范围。特征向量中不同特征之间的不均匀缩放或许会导致聚类算法功能欠安。修正不同特征之间动态范围F M } C E m q不同的一种办法是对特征向量进行规范化。
from segmentation import color_position_features
np.random.seed(0)
features = color_ m * ` a @position_features(i8 S m _ 3 U Wmg)
# 成果检测
assert features.shape == (H * W, C + 2),
"Incorrect shape! Check your implementatiol I E D - e : s wn."
assert features.dtype == np.float,
"dtype of cZ G } c X 7 [ olor_featureC @ p u 5 ]s should be float."
assignmeP ~ t .nts = kmeans_fas ` Lst(features, 8)
segg F s `ments = assignme- y 2 ~ bnts.reshape((H, W))
# 图画切割成果显示
plt.imshow(segments, cmap='F 6 m : g @ 2viridis')
plt.axis('off')
plt.show()
尽管还是存$ ( Q h N在切割不平滑的问7 – ^ 4 i H C Z T题,但现已远好于之前不考虑空域信息的成果了。
visualize_mean_color_image(img,D 4 w T 8 7 [ R E segments)
为了量化评估聚类算法的功能,咱们能够进行定量评估。
咱们利用了一个小型的猫咪图画数据集,并将这些图画切割为远景(cat)和背景(background)。咱们将在这个数据集上定量评估不同的切割办法(特征和聚类办法)。
from utils import load_dataset, compute_segmentation
from segmentation import evaluate_seg` B P { - x j qmentation
## ( R x U U & ) A 载入该小型数据集
imgs, gt_masks = load_dataset('./data1 g ; W ,')
# 设置图画切割的参数
num_seg@ Y k 0 f m * l 5ments = 3
clustering_fn = kmeans_fast
feature_fn = color_features
scale = 0.5
mean_accuracy = 0.0
segmentations] 1 y e Q = []
for i, (img, gt_ma} H p ] 3sk) in enumerate(zip(imgs, gt_masks)):
# Compute a segmentationo C ; for this image
segments = computv x t V 9 9 z e_I f 3 ( ; *segmentation(img, num_segments,
clustering_fn=cluss ( [ i k Wterin] s 3 j mg_fn,
feature_fn=feature_fn,
scale=scale)
segmentations.append(segments)
# 评估图画切割成果
accur? 8 Kacy = evaluate_segmentation(gt_mask, segments)
print('Accuracy for image %d: %0.4f' %(i, accuract B c ; 2 _y))
mean_accuracy += accuracy
mean_accuracy = mean_accuracy / len(imgs)
print('Mean accuracy: %0.4f' % mean_accuracy)
输出成果如下:
Accuracy for image 0: 0.8612
Accuracy for image 1: 0.9571
Accuracy for image 2: 0.9824
Accuracy for image 32 m D U * :: 0.9206
Accu# C 8 c x 3racy for image 4: 0.7642
Accuracy for image 5: 0.8062
Accuracy for image 6: 0.6617
Accuracy for image 7: 0.4726
Accuracy fo_ = Y J | Wr image 8: 0.8317
Accuracy for image 9: 0.7580
Acc@ G Z Sura9 ) F F ]cy forn ; T image 10: 0.6515
Accuracy for image 11: 0.8B @ g ] | - q O R261
Accuracy for image 12: 0.7105
Accuracy for image 13: 0.6667
Accuracy for image 14n A H n ] ! @ X: 0.7623
Accuracy for image 15: 0.5223
Mean accuracy: 0.7597
# 可视化图画切割2 ] V *成果
N = len(imgs)
plt: | L h 1 ; D Z.figure(figsize=(15,60))
for i in range(N):
plt.subplot(N, 3, (i * 3) + 1)
plt.imshoI = T ~w(imgs[i])
plt.ac 4 p P 7 M 7 Oxis('off')
plt.subplot(N, 3, (i * 3) + 2)
plt.imshow(gt_maL * ? qsks[i])
plt.axis('off')
plt.E X F Q 7subplot(N, 3, (i * 3) + 3)
plt.imshow(segmentations[i], cmap='viridis')
plt.axis('off')
plt.show()
你或许还6 h } _ E V t u G会感兴趣
科研基本功——高效文献检索与文献阅读保姆级教程
核算视觉——图画、质量、评价
色彩视觉——杂谈篇
核算视觉——依据暗L = 0 k D通道先验y ; ~ [ R D t . @的图画去雾算法
依据内容的图画缩放
图画手绘/素描风格转换
图画的部分特征信息及全景图画拼接
图画梯度、g + B 3 2 ( & O w图画边缘、几何特征、检测与提取
本博客的代9 e V j i m ^码与数据集可在我的github仓库中找到。
最终求点赞重视二连,您的点赞和重视能让更多人看到这篇文章,蟹蟹!