【图像分割】使用np.where()实现多类别图像分割可视化

人工智能25

目录

背景

方法

背景

相比采用表格化数据定量分析,可视化是分割任务定性分析的主要手段。

在多类别图像分割任务中,往往会涉及两种及以上的颜色,一种常用的方法就是使用RGB色彩填充分割target。

最简单的实现方法就是两次for循环遍历图像,逐个像素进行填充,但这种方式耗时较长,采用np.where()等numpy高级函数可以有效加速,缩短程序运行时间。

方法

以腹部器官数据集Synapse为例,其中包含除去背景一类的8类器官(aorta、gallbladder、liver......),这种情况下,可视化就需要八种颜色来分别表示8类器官,所以先定义对应的颜色:

blue   = [30,144,255] # aorta
green  = [0,255,0]    # gallbladder
red    = [255,0,0]    # left kidney
cyan   = [0,255,255]  # right kidney
pink   = [255,0,255]  # liver
yellow = [255,255,0]  # pancreas
purple = [128,0,255]  # spleen
orange = [255,128,0]  # stomach

这里选取了几种对比较为鲜明的颜色。

接下来需要处理一下原始图像以及预测结果,一般来说作为模型的输入,原始图像一般会经过归一化操作,所以乘以255恢复原始像素值,在转换为uint8格式以使用opencv处理。此外,原始图像若是灰度图还需转换为3通道的RGB格式。分割结果默认是非one-hot的一维格式(通过torch.argmax转换得到),所以也需要转换为RGB三维格式:

original_img = original_img * 255.0
original_img = original_img.astype(np.uint8)
original_img = cv2.cvtColor(original_img,cv2.COLOR_GRAY2BGR)
pred = cv2.cvtColor(pred,cv2.COLOR_GRAY2BGR)

接下来是核心部分,以其中一类为例:

original_img = np.where(pred==1, np.full_like(original_img, blue), original_img)

np.where(condition, x, y) 函数定义如下:满足条件(condition),输出x,不满足输出y,具体可参考点击跳转。此处的条件是判断预测结果的某一像素点是否为"1"类别,若是则使用定义好的"blue"RGB值填充(np.full_like的作用是创建一个等于原图大小的全蓝色图像,多余的蓝色区域可以被pred掩膜过滤掉),若不是则输出原始图像的像素值。分别对8类处理完后保存即可,最终可视化结果如图(左:原图,右:分割结果):

【图像分割】使用np.where()实现多类别图像分割可视化【图像分割】使用np.where()实现多类别图像分割可视化

完整代码如下,输入分别为原图,预测结果,可视化结果保存路径:

def vis_save(original_img, pred, save_path):
    blue   = [30,144,255] # aorta
    green  = [0,255,0]    # gallbladder
    red    = [255,0,0]    # left kidney
    cyan   = [0,255,255]  # right kidney
    pink   = [255,0,255]  # liver
    yellow = [255,255,0]  # pancreas
    purple = [128,0,255]  # spleen
    orange = [255,128,0]  # stomach
    original_img = original_img * 255.0
    original_img = original_img.astype(np.uint8)
    original_img = cv2.cvtColor(original_img,cv2.COLOR_GRAY2BGR)
    pred = cv2.cvtColor(pred,cv2.COLOR_GRAY2BGR)
    original_img = np.where(pred==1, np.full_like(original_img, blue  ), original_img)
    original_img = np.where(pred==2, np.full_like(original_img, green ), original_img)
    original_img = np.where(pred==3, np.full_like(original_img, red   ), original_img)
    original_img = np.where(pred==4, np.full_like(original_img, cyan  ), original_img)
    original_img = np.where(pred==5, np.full_like(original_img, pink  ), original_img)
    original_img = np.where(pred==6, np.full_like(original_img, yellow), original_img)
    original_img = np.where(pred==7, np.full_like(original_img, purple), original_img)
    original_img = np.where(pred==8, np.full_like(original_img, orange), original_img)
    original_img = cv2.cvtColor(original_img,cv2.COLOR_BGR2RGB)
    cv2.imwrite(save_path, original_img)

实测结果表明,使用np.where()函数实现可比双for循环遍历快6倍左右。

Original: https://blog.csdn.net/qq_40475568/article/details/122012164
Author: McGregorWwww
Title: 【图像分割】使用np.where()实现多类别图像分割可视化



相关阅读1

Title: 19.高通滤波

上一节为低通滤波,最主要的作用是去噪

高斯滤波去除高斯噪声

中值滤波去除椒盐噪声

双边噪声用于美颜

高通滤波最主要的作用是用于检测边缘

常见的高通滤波:

  • Sobel(索贝尔)(高斯),对噪声适应性强,很多算法均以索贝尔卷积核为基础
  • Scharr(沙尔), 卷积核不会改变,3*3大小,如果Sobel(索贝尔)的size设为-1,则自动使用的则为沙尔滤波,所以一般情况下均使用索贝尔算法。

对于3*3的卷积核,Sobel(索贝尔)没有Scharr(沙尔)好,因为Scharr(沙尔)可以检测出更细的边缘线。Sobel(索贝尔)比较粗糙

缺点:计算边缘时,只能求一个方向,要么是横轴,要么是纵轴,最后再相加的出最终结果

  • Laplacian(拉普拉斯),优点不需要单独求x或y的边缘,可以直接将横轴和纵轴的边缘全部检测出来。

缺点:对噪声比较敏感,在其内部没有降噪的功能,因此在使用前,需要进行降噪处理。

Sobel算子

  • 先对X方向求导
  • 再对Y方向求导
  • 最终结果进行累加
  • 注:不能两个方向同时求

Sobel API

Sobel(src, ddepth, dx, dy, ksize = 3,scale = 1,delte = 0,borderType = BORDER_DEFAULT)

ddepth 输出的位深,64位或32位

卷积核大小默认为3,可以改为5,7,若为-1则变为为沙尔算法

import cv2
import numpy as np

img = cv2.imread('E:\\112.png')

#索贝尔算子Y方向边缘
dst1 = cv2.Sobel(img,cv2.CV_64F,1,0)

#索贝尔算子X方向边缘
dst2 = cv2.Sobel(img,cv2.CV_64F,0,1)

#两个方向进行合并
dst3 = dst1 + dst2
#dst3 = cv2.add(d1,d2)  这种方法效率更高

cv2.imshow('img',img)
cv2.imshow('dst1',dst1)
cv2.imshow('dst2',dst2)
cv2.imshow('dst3',dst3)

cv2.waitKey(0)

【图像分割】使用np.where()实现多类别图像分割可视化

Scharr(沙尔)算子

与Sobel类似,只不过使用的kernel值不同,只支持3*3的卷积核

Scharr(沙尔)只能求x方向或y方向的边缘,重点还是索贝尔算子

简单修改即为沙尔算子,沙尔可以检测出更小的边缘

【图像分割】使用np.where()实现多类别图像分割可视化

拉普拉斯算子

  • 可以同时求两个方向的边缘
  • 缺点:对噪声比较敏感,一般需要先进行去噪再调用拉普拉斯算子

对应API

Laplacian(img, ddepth, ksize =1, scale = 1,borderType = BORDER_DEFAULT)

#拉普拉斯算子
dst4 = cv2.Laplacian(img, cv2.CV_64F,ksize=5)

cv2.imshow('dst4',dst4)
cv2.waitKey(0)

【图像分割】使用np.where()实现多类别图像分割可视化

边缘检测 Canny

边缘检测效果最好,主要有以下步骤

  • 使用5*5高斯滤波消除噪声
  • 计算图像梯度的方向(0°/45°/90°/135°)共四个方向
  • 在四个方向上取局部最大值
  • 取出最大值后进行阈值计算

【图像分割】使用np.where()实现多类别图像分割可视化

AC是边缘,B不是边缘,小于阈值不认为是边缘,大于阈值认为是边缘

Canny API

重要的是前3个参数

Canny(img, minVAL, maxVal,....)

import cv2
import numpy as np

img = cv2.imread('E:\\112.png')

dst = cv2.Canny(img,100,200)

cv2.imshow('img',img)
cv2.imshow('dst',dst)

cv2.waitKey(0)

【图像分割】使用np.where()实现多类别图像分割可视化

具体的边缘跟设定的阈值有关

Original: https://blog.csdn.net/qq_45355603/article/details/125261353
Author: ⁢稚子
Title: 19.高通滤波

相关阅读2

Title: arm64/x64/x86/macos安装tensorflow c语言版本

请认真阅读以下内容:
本人应该把能踩过的坑全部都踩了(2days)
我把所有坑和解决方案都记录下来(纯文字)
建议先看完某一个大步骤以及了解踩坑原因再执行对应的命令能够有效避免踩坑
本文包括:
(1)官方编译好的动态库(x86,x64)以及我编译好的动态库(arm64)
(2)安装树莓派64位系统
(3)安装bazel(编译tensorflow工具):脚本和编译两个方式
(4)安装tensorflow:编译和直接下载使用两个方式

直接下载(推荐方式):

x86和x64可以直接下载官方编译好的动态链接库,然后跳到安装tensorflow编译完成:
Linux(仅支持 CPU) https://storage.googleapis.com/tensorflow/libtensorflow/libtensorflow-cpu-linux-x86_64-2.6.0.tar.gz
Linux(支持 GPU) https://storage.googleapis.com/tensorflow/libtensorflow/libtensorflow-gpu-linux-x86_64-2.6.0.tar.gz
macOS(仅支持 CPU) https://storage.googleapis.com/tensorflow/libtensorflow/libtensorflow-cpu-darwin-x86_64-2.6.0.tar.gz
Windows(仅支持 CPU) https://storage.googleapis.com/tensorflow/libtensorflow/libtensorflow-cpu-windows-x86_64-2.6.0.zip
Windows(仅支持 GPU) https://storage.googleapis.com/tensorflow/libtensorflow/libtensorflow-gpu-windows-x86_64-2.6.0.zip

我编译的树莓派arm64版本:

下载完直接跳到安装步骤

编译安装(不建议方式):

观前提醒(背景):
1.

编译过程十分漫长,你可能需要一天的时间来搞,建议看剧消磨时间
影视推荐:猎魔人,纸牌屋,洛基
2.

如果想要尝试,建议树莓派4B(64位)配置:4G内存+32Gtf卡
编译过程十分耗资源,当然,内存2G应该也行,就是要慢一点(我会有提示,请注意)
我就是4+32,,重装了树莓派64位系统后直接下载编译tensorflow过程中
tf卡占用如下:
Filesystem Size Used Avail Use% Mounted on
/dev/root 29G 14G 15G 49% /
devtmpfs 1.7G 0 1.7G 0% /dev
tmpfs 1.9G 0 1.9G 0% /dev/shm
tmpfs 1.9G 492K 1.9G 1% /run
tmpfs 5.0M 4.0K 5.0M 1% /run/lock
tmpfs 1.9G 0 1.9G 0% /sys/fs/cgroup
/dev/mmcblk0p1 253M 30M 223M 12% /boot
tmpfs 380M 0 380M 0% /run/user/1000
编译时某一时刻内存占用如下:
total used free shared buff/cache available
Mem: 3.7Gi 3.6Gi 34Mi 0.0Ki 104Mi 63Mi
Swap: 4.0Gi 933Mi 3.1Gi
以及
total used free shared buff/cache available
Mem: 3.7Gi 3.5Gi 43Mi 0.0Ki 137Mi 105Mi
Swap: 4.0Gi 1.1Gi 2.9Gi
大部分时候内存占用基本情况(具有一定代表性):
total used free shared buff/cache available
Mem: 3.7Gi 1.9Gi 1.6Gi 0.0Ki 263Mi 1.8Gi
Swap: 4.0Gi 597Mi 3.4Gi
以及
total used free shared buff/cache available
Mem: 3.7Gi 2.7Gi 786Mi 0.0Ki 215Mi 925Mi
Swap: 4.0Gi 420Mi 3.6Gi
3.

我的环境:
- 系统64位,没超频
- 内核:Linux raspberrypi 5.10.63-v8+ #1496 SMP PREEMPT Wed Dec 1 15:59:46 GMT 2021 aarch64 GNU/Linux
- 硬件 :4+32

Original: https://blog.csdn.net/qq_44113911/article/details/122603588
Author: 在退学边缘疯狂试探
Title: arm64/x64/x86/macos安装tensorflow c语言版本

相关阅读3

Title: TensorFlow读书笔记

1.TensorFlow基础知识:

Tensor(张量)意味着N维数组,Flow(流)意味着基于数据流图的计算.数据流图中的图就是我们所说的有向图,我们知道,在图这种数据结构中包含两种基本元素:节点和边.这两种元素在数据流图中有自己各自的作用.节点用来表示要进行的数学操作,另外,任何一种操作都有输入/输出,因此它也可以表示数据的输入的起点/输出的终点.边表示节点与节点之间的输入/输出关系,一种特殊类型的数据沿着这些边传递.这种特殊类型的数据在TensorFlow被称之为tensor,即张量,所谓的张量通俗点说就是多维数组.当我们向这种图中输入张量后,节点所代表的操作就会被分配到计算设备完成计算.

TensorFlowd的四个特性:

灵活性
可移植性
多语言支持
高效性

Graph:要组装的结构,由许多操作组成,其中的每个连接点代表一种操作

op:接受(流入)零个或多个输入(液体),返回(流出)零个或多个输出

2.实验:

import tensorflow as tf
from tensorflow import keras
import numpy as np
import matplotlib.pyplot as plt
fashion_mnist=keras.datasets.fashion_mnist
(train_images,train_labels),(test_images,test_labels)=fashion_mnist.load_data()
class_names=['T-shirt/top','Trouser','Pullover','Dress','Coat','Sandal','Shirt','Sneaker','Bag','Ankle boot']
train_labels
train_images.shape
len(train_labels)
test_images.shape
len(test_labels)
plt.figure()
plt.imshow(train_images[0])
plt.colorbar()
plt.grid(False)
plt.show()
train_images=train_images/255.0
test_images=test_images/255.0
plt.figure(figsize=(10,10))
for i in range(25):
    plt.subplot(5,5,i+1)
    plt.xticks([])
    plt.yticks([])
    plt.grid(False)
    plt.imshow(train_images[i],cmap=plt.cm.binary)
    plt.xlabel(class_names[train_labels[i]])
plt.show()
model=keras.Sequential([
    keras.layers.Flatten(input_shape=(28,28)),
    keras.layers.Dense(128,activation='relu'),
    keras.layers.Dense(10)])
model.compile(optimizer='adam',
              loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
              metrics=['accuracy'])
model.fit(train_images,train_labels,epochs=10)
test_loss,test_acc=model.evaluate(test_images,test_labels,verbose=2)
print('\nTest accuracy:',test_acc)
probability_model=tf.keras.Sequential([model,
                                       tf.keras.layers.Softmax()])
predictions=probability_model.predict(test_images)
predictions[0]
np.argmax(predictions[0])
test_labels[0]
def plot_image(i,predictions_array,true_label,img):
    predictions_array, true_label, img=predictions_array, true_label[i], img[i]
    plt.grid(False)
    plt.xticks([])
    plt.yticks([])
    plt.imshow(img, cmap=plt.cm.binary)
    predicted_label = np.argmax(predictions_array)
    if predicted_label == true_label:
        color = 'blue'
    else:
        color = 'red'

    plt.xlabel("{} {:2.0f}% ({})".format(class_names[predicted_label],
                                         100*np.max(predictions_array),
                                         class_names[true_label]),
                                         color=color)

def plot_value_array(i, predictions_array, true_label):
    predictions_array, true_label = predictions_array, true_label[i]
    plt.grid(False)
    plt.xticks(range(10))
    plt.yticks([])
    thisplot = plt.bar(range(10), predictions_array, color="#777777")
    plt.ylim([0, 1])
    predicted_label = np.argmax(predictions_array)

    thisplot[predicted_label].set_color('red')
    thisplot[true_label].set_color('blue')
i = 0
plt.figure(figsize=(6,3))
plt.subplot(1,2,1)
plot_image(i, predictions[i], test_labels, test_images)
plt.subplot(1,2,2)
plot_value_array(i,predictions[i],test_labels)
plt.show()
Plot the first X test images, their predicted labels, and the true labels.

Color correct predictions in blue and incorrect predictions in red.

num_rows = 5
num_cols = 3
num_images = num_rows*num_cols
plt.figure(figsize=(2*2*num_cols, 2*num_rows))
for i in range(num_images):
    plt.subplot(num_rows,2*num_cols,2*i+1)
    plot_image(i, predictions[i], test_labels, test_images)
    plt.subplot(num_rows, 2*num_cols, 2*i+2)
    plot_value_array(i, predictions[i], test_labels)
plt.tight_layout()
plt.show()
#测试部分
img=test_images[1]
print(img.shape)
img=(np.expand_dims(img,0))
print(img.shape)
predictions_single=probability_model.predict(img)
print(predictions_single)
plot_value_array(1,predictions_single[0],test_labels)
_ =plt.xticks(range(10),class_names,rotation=45)
np.argmax(predictions_single[0])

【图像分割】使用np.where()实现多类别图像分割可视化【图像分割】使用np.where()实现多类别图像分割可视化

【图像分割】使用np.where()实现多类别图像分割可视化【图像分割】使用np.where()实现多类别图像分割可视化

【图像分割】使用np.where()实现多类别图像分割可视化

课后习题:

(1)局部连接:层间神经只有局部范围内的连接,在这个范围内采用全连接的方式,超过这个范围的神经元则没有连接;连接与连接之间独立参数,相比于去全连接减少了感受域外的连接,有效减少参数规模。

全连接:层间神经元完全连接,每个输出神经元可以获取到所有神经元的信息,有利于信息汇总,常置于网络末尾;连接与连接之间独立参数,大量的连接大大增加模型的参数规模。

(2)卷积运算原理,最基本的就是单通道对应一个输出通道,那就用一个二维矩阵对输入图像进行运算,提取图像特征。但是单通道输入得到多通道(k个通道)输出,就需要k个滤波器,每个滤波器是就是一个二维的33矩阵,也就是每个滤波器包含一个卷积核。但是当输入是多通道(t)得到多通道(k个通道)输出,那这次卷积就包括k个滤波器,每个滤波器就是一个3维矩阵,33t,每个滤波器就包含t个卷积核。上面输出通道是k,那就得到了k个特征图,每个输出通道就是一个特征图。

(3)池化的目的:对输入的特征图进行压缩,一方面使特征图变小,简化网络计算复杂度;一方面进行特征压缩,提取主要特征。

激活函数的作用:如果不用激励函数,每一层输出都是上层输入的线性函数,无论神经网络有多少层,输出都是输入的线性组合。如果使用的话,激活函数给神经元引入了非线性因素,使得神经网络可以任意逼近任何非线性函数,这样神经网络就可以应用到众多的非线性模型中。

(4).归一化有助于快速收敛;. 2.对局部神经元的活动创建竞争机制,使得其中响应比较大的值变得相对更大,并抑制其他反馈较小的神经元,增强了模型的泛化能力。

(5)寻找损失函数的最低点,就像我们在山谷里行走,希望找到山谷里最低的地方。那么如何寻找损失函数的最低点呢?在这里,我们使用了微积分里导数,通过求出函数导数的值,从而找到函数下降的方向或者是最低点(极值点)。损失函数里一般有两种参数,一种是控输入信号量的权重,另一种是调整函数与真实值距离的偏差。我们所要做的工作,就是通过梯度下降方法,不断地调整权重 和偏差b,使得损失函数的值变得越来越小。

Original: https://blog.csdn.net/weixin_58565789/article/details/124389375
Author: weixin_58565789
Title: TensorFlow读书笔记

相关文章
人工智能

单元测试

前言 对于现在的前端工程,一个标准完整的项目,通常情况单元测试是非常必要的。但很多时候我们只是完成了项目而忽略了项目测试。我认为其中一个很大的原因是很多人对单元测试认知不够,因此我写了这边文章,一方面...
人工智能

WIN10平板 传递优化文件能否删除

这个文件只是WIN10改进了系统更新策略产生的,就像是BTB下载的临时文件,方便自己更新,也方便别人更新。但是我们一般很讨厌Windows自动更新,所以不但这个文件要删除,还要防止WIN10再次自动更...
人工智能

声纹识别_

声纹识别和语音识别的区别 1.两者在原理上一样,都是通过采集语音信息进行分析和处理,提取相应的特征或建立模型,然后做出判断 2.两者识别的目的:语音识别通过识别说话的内容转化为文字,而声纹识别则是要识...
人工智能

Win10系统的SurfacePro4的触摸笔如何使用

初次使用需要配对,微软的触摸笔是蓝牙配对的,打开平板的蓝牙,长按触摸笔后面的按钮,触摸笔会闪烁小灯,平板会提示配对准备已就绪 点击配对之后,提示已连接 可以按下触摸笔后面的按钮,一键打开OneNote...
人工智能

NLP赛事电商搜索

本次题目围绕电商领域搜索算法,开发者们可以通过基于阿里巴巴集团自研的高性能分布式搜索引擎问天引擎(提供高工程性能的电商智能搜索平台),可以快速迭代搜索算法,无需自主建设检索全链路环境。 本次评测的数据...