首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >Python 图像处理—使用 Scikit-Image 进行斑点检测

Python 图像处理—使用 Scikit-Image 进行斑点检测

作者头像
AI算法与图像处理
发布2021-03-12 14:53:41
发布2021-03-12 14:53:41
2.2K0
举报

引言

图像处理时,我们需要的最重要的技能之一就是能够识别图像中的特定部分。一张图片只有在特定的感兴趣点能够被识别和分别列出的情况下才有用。在本文中,我们将了解如何做到这一点。

让我们从导入本文所需的库开始!

代码语言:javascript
复制
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import skimage
from skimage.io import imread, imshow
from skimage.color import rgb2gray, rgb2hsv
from skimage.measure import label, regionprops, regionprops_table
from skimage.filters import threshold_otsu
from scipy.ndimage import median_filter
from matplotlib.patches import Rectangle
from tqdm import tqdm

现在让我们加载图像。

代码语言:javascript
复制
tree = imread('laughing_tree.png')
imshow(tree);

我们的任务是识别和隔离图像中包含树木独特果实的部分(看起来像张开的嘴)。

首先让我们尝试看看是否有任何简单的方法来基于图像的值进行识别。让我们将图像转换为灰度,并使用 Otsu 方法。

代码语言:javascript
复制
tree_gray = rgb2gray(tree)
otsu_thresh = threshold_otsu(tree_gray)
tree_binary = tree_gray < otsu_thresh
imshow(tree_binary, cmap = 'gray');

这显然不能很好地解决这个问题,让我们尝试在几个不同阈值上进行迭代。

代码语言:javascript
复制
def threshold_checker(image):
    thresholds =  np.arange(0.1,1.1,0.1)
    tree_gray = rgb2gray(image)
    fig, ax = plt.subplots(2, 5, figsize=(17, 10))
    for n, ax in enumerate(ax.flatten()):
        ax.set_title(f'Threshold  : {round(thresholds[n],2)}',      
                       fontsize = 16)
        threshold_tree = tree_gray < thresholds[n]
        ax.imshow(threshold_tree);
        ax.axis('off')
    fig.tight_layout()
threshold_checker(tree)

我们可以看到,尽管阈值处理似乎有所帮助,但它仍然包含了我们不感兴趣的图像部分。让我们尝试另一种方法。

代码语言:javascript
复制
tree_hsv = rgb2hsv(tree[:,:,:-1])
plt.figure(num=None, figsize=(8, 6), dpi=80)
plt.imshow(tree_hsv[:,:,0], cmap='hsv')
plt.colorbar();

如果将图像放入HSV色彩空间中,我们可以看到水果明显具有红色色调,该红色色调在图像的其他部分不存在。让我们尝试分离图像的这些部分。

代码语言:javascript
复制
lower_mask = tree_hsv [:,:,0] > 0.80
upper_mask = tree_hsv [:,:,0] <= 1.00
mask = upper_mask*lower_mask
red = tree[:,:,0]*mask
green = tree[:,:,1]*mask
blue = tree[:,:,2]*mask
tree_mask = np.dstack((red,green,blue))
plt.figure(num=None, figsize=(8, 6), dpi=80)
imshow(tree_mask);

可以看到,除了果实,还保留了大部分的天空部分。参考上一个色相通道图像,我们可以看到这些部分在水果中也存在相同种类的红色。

为了解决这个问题,让我们检查一下图像的 Value 通道。

代码语言:javascript
复制
tree_hsv = rgb2hsv(tree[:,:,:-1])
plt.figure(num=None, figsize=(8, 6), dpi=80)
plt.imshow(tree_hsv[:,:,2], cmap='gray')
plt.colorbar();

可以看到那些明亮区域的值非常的高,在创建mask的时候我们需要考虑这一点。

代码语言:javascript
复制
lower_mask = tree_hsv [:,:,0] > 0.80
upper_mask = tree_hsv [:,:,0] <= 1.00
value_mask = tree_hsv [:,:,2] < .90
mask = upper_mask*lower_mask*value_mask
red = tree[:,:,0] * mask
green = tree[:,:,1] * mask
blue = tree[:,:,2] * mask
tree_mask = np.dstack((red, green, blue))
plt.figure(num=None, figsize=(8, 6), dpi=80)
imshow(tree_mask);

很好!现在我们需要找到一种方法来清理图像中的小白点。为此,我们可以简单地使用 Skimage 库中的中值滤波函数。

代码语言:javascript
复制
lower_mask = tree_hsv [:,:,0] > 0.80
upper_mask = tree_hsv [:,:,0] <= 1.00
value_mask = tree_hsv [:,:,2] < .90
mask = median_filter(upper_mask*lower_mask*value_mask, 10)
red = tree[:,:,0] * mask
green = tree[:,:,1] * mask
blue = tree[:,:,2] * mask
tree_mask = np.dstack((red, green, blue))
plt.figure(num=None, figsize=(8, 6), dpi=80)
imshow(tree_mask);

可以看到,结合了中值过滤器可以使我们获得非常清晰的图像。现在我们需要标识每个,为此,我们需要使用 Skimage 中的 label 函数。

代码语言:javascript
复制
tree_blobs = label(rgb2gray(tree_mask) > 0)
imshow(tree_blobs, cmap = 'tab10');

可以看到该函数标识了图像中的不同。现在的下一步是获取每个斑点的属性。为此,我们需要使用 Skimage 中的 regionprops_table 函数。

代码语言:javascript
复制
properties =['area','bbox','convex_area','bbox_area',
             'major_axis_length', 'minor_axis_length',
             'eccentricity']
df = pd.DataFrame(regionprops_table(tree_blobs, properties = properties))

regionprops_table 函数在数据帧中为我们提供每个斑点的属性,这使我们能够轻松地操作数据。让我们使用bbox特性在图像上绘制边界框。

代码语言:javascript
复制
blob_coordinates = [(row['bbox-0'],row['bbox-1'],
                     row['bbox-2'],row['bbox-3'] )for 
                    index, row in df.iterrows()]
fig, ax = plt.subplots(1,1, figsize=(8, 6), dpi = 80)
for blob in tqdm(blob_coordinates):
    width = blob[3] - blob[1]
    height = blob[2] - blob[0]
    patch = Rectangle((blob[1],blob[0]), width, height, 
                       edgecolor='r', facecolor='none')
    ax.add_patch(patch)
ax.imshow(tree);
ax.set_axis_off()

成功了!

最后,让我们从图像中切出边界框,并将其显示为自己的图像。

代码语言:javascript
复制
fig, ax = plt.subplots(1, len(blob_coordinates), figsize=(15,5))
for n, axis in enumerate(ax.flatten()):
    axis.imshow(tree[int(blob_coordinates[n][0]):
                     int(blob_coordinates[n][2]), 
                     int(blob_coordinates[n][1]):
                     int(blob_coordinates[n][3])]);
    
fig.tight_layout()

总结

了解如何进行斑点检测对于图像处理来说都是非常重要的。它可以用来将图像的不同部分分割成不同的兴趣点。虽然这是一个相对简单和直接的介绍,但希望对你哟一个启发性的认识,如何通过使用斑点检测来解决基本的图像问题。

· END ·

HAPPY LIFE

代码语言:javascript
复制
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-03-08,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 AI算法与图像处理 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档