首页 > 其他分享 >用OpenCV进行传统图像分割

用OpenCV进行传统图像分割

时间:2023-07-03 21:32:26浏览次数:32  
标签:分割 plt 20 img image ax OpenCV 图像 new

1. 引言

欢迎回来,我的图像处理爱好者们!本文我们将直接进入传统图像分析的新领域——图像分割,这是指将图像分成若干具有相似性质的区域的过程,从数学角度来看,图像分割是将图像划分成互不相交的区域的过程。 闲话少说,我们直接开始吧!

2. 基于阈值的分割

首先介绍的是基于阈值和基于Otsu的分割方法,这是我们进行分割实验的第一步,我们将了解像这样简单而有效的方法是如何根据图像像素的强度值将图像划分为前景和背景两部分的。

但是我们如何科学地决定分割的阈值呢?这就是Otsu方法派上用场的地方。简单地说,这种巧妙的方法通过计算出最大化类间方差的最佳阈值,使其成为自适应阈值选择的优秀工具。

首先从我们的准备工作开始, 导入我们需要的图像处理库:

# Import libraries
from skimage.io import imread, imshow
import matplotlib.pyplot as plt
import numpy as np
from skimage.color import rgb2gray, rgb2hsv
from skimage.filters import threshold_otsu

加载本节测试图像样例,如下:

# Display the image that we will be playing with
original_image = imread('plants.jpg')
plt.figure(figsize=(20,20))
plt.imshow(original_image)
plt.title('Original Image', fontsize=20, weight='bold')
plt.axis('off')
plt.show()

结果如下:

用OpenCV进行传统图像分割_图像分割

3. 固定阈值分割

当我们想要对图像进行二值化时,我们执行两步过程,将图像转换为灰度图,然后设置我们想要的任何阈值(通常为0.50),进而将其转换为二值图像:

# Convert the image to grayscale
gray_image = rgb2gray(original_image)
plt.figure(figsize=(20,20))
plt.imshow(gray_image, cmap='gray')
plt.title('Grayscale Image', fontsize=20, weight='bold')
plt.axis('off')
plt.show()

得到灰度图,结果如下:

用OpenCV进行传统图像分割_图像分割_02

选择固定阈值,进行二值化,代码如下:

# Convert the grayscale image to binary image using threshold=0.50
threshold = 0.5
binary_image = gray_image<threshold
plt.figure(figsize=(20,20))
plt.imshow(binary_image, cmap='gray')
plt.title('Binary Image', fontsize=20, weight='bold')
plt.axis('off')
plt.show()

得到二值图效果如下:

用OpenCV进行传统图像分割_图像处理_03

观察上图,可以发现对于前景背景区分度比较明显的图像,通过设置固定的阈值也可以方便的得到我们需要的前景物体。

4. 自适应阈值分割

请注意分析上述图像中原本较亮的部分是如何变黑的,这是因为我们使用了0.50作为阈值。但在Otsu的方法中,我们不必手动设置阈值,我们可以通过调用函数threshold_otsu让Otsu为我们处理这项工作,如下所示:

# Use threshold_otsu to automatically calculate the optimal threshold
threshold = threshold_otsu(gray_image)
print(f"Otsu's Threshold: {threshold:.2f}")
binary_image_otsu  = gray_image < threshold
plt.figure(figsize=(20,20))
plt.imshow(binary_image_otsu, cmap='gray')
plt.title("Binary Image using Otsu's Method", fontsize=20, weight='bold')
plt.axis('off')
plt.show()

结果如下:

Output:
Otsu's Threshold: 0.67

得到二值图的效果如下:

用OpenCV进行传统图像分割_图像处理_04

看到区别了吗?我们不必为了获得更好的二值化图像而手动地对阈值进行试错。多亏了otsu的方法,为我们节省了大量试错时间!

5. 彩色图像分割

假设我们只想在图像中隔离青色的植物,那么是时候采用另一种令人兴奋的技术了——彩色图像分割!这种方法是二值化的扩展,但这里有一个注意项:我们使用颜色信息来分离对象,而不是像素值强度。当图像中感兴趣的对象拥有独特不同的颜色时,该方法特别有用。

按照惯例,我们还是首先导入我们的样例图像,代码如下:

# Display original image
original_image = imread('plants.jpg')
plt.figure(figsize=(20,20))
imshow(original_image)
plt.title('Original Image', fontsize=20, weight='bold')
plt.axis('off')
plt.show()

结果如下:

用OpenCV进行传统图像分割_图像分割_05

6. 基于RGB颜色空间的图像分割

观察上图,为了只隔离茂盛的绿色植物,我们可以执行简单的分割操作。如果绿色通道值大于红色和蓝色通道值,我们可以使用下面的比较运算符来表示像素为绿色,代码如下:

# Read image using skimage
original_image = imread('plants.jpg')

# Create subplot of 1x2
fig, ax = plt.subplots(1, 2, figsize=(20, 20))

# Plot original image
ax[0].imshow(original_image)
ax[0].set_title('Original Image', fontsize=20, weight='bold')
ax[0].axis('off')

# Get red, green, and blue channels
r = original_image[:, :, 0]
g = original_image[:, :, 1]
b = original_image[:, :, 2]

# Create a mask for green color
mask = (g > r) & (g > b) # adjust these values depending on what you consider to be 'green'

# Create a new image
new_img = original_image.copy()

# Apply mask to all channels
new_img[:, :, 0] = new_img[:, :, 0] * mask
new_img[:, :, 1] = new_img[:, :, 1] * mask
new_img[:, :, 2] = new_img[:, :, 2] * mask

# Plot the green segmented image
ax[1].imshow(new_img)
ax[1].set_title('Green Segmented Image', fontsize=20, weight='bold')
ax[1].axis('off')

# Display the subplot
plt.tight_layout()
plt.show()

结果如下:

用OpenCV进行传统图像分割_图像分割_06

7. 美化效果

观察上述右图,虽然我们可以大致得到我们想要的分割结果,但是仔细观察上图中留下了很多无用的白色标记。实质上白色是红色、绿色和蓝色都达到顶峰的颜色。因此,为了阻止这些不想要的因素,我们可以在代码中添加一个白色掩膜,代码如下:

# Create a mask for white color
white_threshold = 180  # adjust this depending on what you consider to be 'white'
white_mask = (r > white_threshold) & (g > white_threshold) & (b > white_threshold)
# Combine the green and white masks
mask = green_mask & ~white_mask  # ~ is the NOT operator
# Create a new image and apply mask
new_img = original_image.copy()
# Apply mask to all channels
new_img[:,:,0] = new_img[:,:,0] * mask
new_img[:,:,1] = new_img[:,:,1] * mask
new_img[:,:,2] = new_img[:,:,2] * mask

# Plot the green segmented image
ax[1].imshow(new_img)
ax[1].set_title('Green Segmented Image', fontsize=20, weight='bold')
ax[1].axis('off');

得到结果如下:

用OpenCV进行传统图像分割_图像分割_07

8. 基于HSV颜色空间的图像分割

如上所述,有时在其他颜色空间(如HSV(色调、饱和度、值))中分割颜色更容易。在HSV颜色空间中,不同的颜色排列在一个圆上(色调),因此挑选特定的颜色可能更容易。

让我们显示原始图像的色调、饱和度和值:

# Read image using skimage
original_image = imread('plants.jpg')

# Convert the image to HSV color space
hsv_img = rgb2hsv(original_image)

fig, ax = plt.subplots(1, 3, figsize=(20,20))
ax[0].imshow(hsv_img[:,:,0], cmap='hsv')
ax[0].set_title('Hue', fontsize=20)
ax[1].imshow(hsv_img[:,:,1], cmap='hsv')
ax[1].set_title('Saturation', fontsize=20)
ax[2].imshow(hsv_img[:,:,2], cmap='hsv')
ax[2].set_title('Value', fontsize=20);

结果如下:

用OpenCV进行传统图像分割_图像分割_08

9. 基于HSV颜色空间的图像分割

由于使用上面的图很难看到强度值的差异,所以让我们使用colorbar函数来分析,代码如下:

plt.imshow(hsv_img[:,:,0], cmap='hsv')
plt.colorbar()

结果如下:

用OpenCV进行传统图像分割_图像处理_09

正如你所看到的,橙色介于0到0.05之间,所以让我们这些值作为阈值:

# Read image using skimage
original_image = imread('plants.jpg')

# Convert the image to HSV color space
hsv_img = rgb2hsv(original_image)

# Create a mask for orange color
# Hue for orange is roughly in the range of 0 - 0.05
# We can play around these values to adapt to our specific color requirement
mask = (hsv_img[:,:,0] > 0) & (hsv_img[:,:,0] < 0.05)

# create a new image and apply mask
new_img = original_image.copy()

new_img[:,:,0] = new_img[:,:,0] * mask
new_img[:,:,1] = new_img[:,:,1] * mask
new_img[:,:,2] = new_img[:,:,2] * mask

# plot the original and segmented images side by side
fig, ax = plt.subplots(1, 2, figsize=(20,10))

ax[0].imshow(original_image)
ax[0].set_title('Original Image', fontsize=20, weight='bold')
ax[0].axis('off')

ax[1].imshow(new_img)
ax[1].set_title('Orange Segmented Image', fontsize=20, weight='bold')
ax[1].axis('off')

plt.show()

结果如下:

用OpenCV进行传统图像分割_图像处理_10

观察上图,我们已经成功地在植物图像中分割出了具有鲜艳色调的橙色植物。

10.总结

哇,我们今天的旅程简直太棒了!我们对图像分割的深入研究无疑为我们如何从图像中提取有意义的信息提供了有效的方法。 希望大家可以通过上述案例,进入到图像处理的神秘领域,感叹相关算法的魅力。

标签:分割,plt,20,img,image,ax,OpenCV,图像,new
From: https://blog.51cto.com/u_15506603/6615879

相关文章

  • 图像识别,如何提取文字?在线提取图片文字内容(批量)
    功能地址在线文字识别,OCR识别,提取图片文字内容,图像转文字教程,批量免费|TOFORU在线工具软件定制地址:https://tool.toforu.com/f/img_text.html功能说明在线文字识别,提取图片文字内容,图像转文字。功能使用原图上传识别提取文字结果下载结果txt文件,可看到提取到......
  • 帧数指的是每秒播放的图像帧数,单位为fps(Frames Per Second)。视频由一系列静止的图像帧
    视频的帧数指的是每秒播放的图像帧数,单位为fps(FramesPerSecond)。视频由一系列静止的图像帧组成,通过快速连续地播放这些图像帧,就能够呈现出连续的动态影像。帧数的概念源自电影行业。在电影制作中,通过连续播放一系列静态图像(称为帧),来创造出连贯的动画效果。每秒钟播放的帧数越多......
  • OpenCV:最流行的图像处理库
    https://www.cnblogs.com/traditional/p/11193524.html楔子关于Python的图像处理,我们之前介绍一个第三方库叫PIL,现在我们来介绍另一个库OpenCV。从功能和性能上来讲,OpenCV要比PIL强大很多,而且OpenCV还可以处理视频。那么下面我们就来介绍一下OpenCV的用法,首先是安......
  • 可分割背包问题
    我绝对不会告诉你我做了8遍才过这道题题目现在有很多物品(它们是可以分割的),我们知道它们每个物品的单位重量的价值v和重量w(1<=v,w<=10);如果给你一个背包,它能容纳的重量为m(10<=m<=20),你所要做的就是把物品装到背包里,使背包里的物品的价值总和最大。Input第一行输入一个正整......
  • opencv: mask
    (20条消息)pythonopencv图像叠加/图像融合/mask掩模_cv2读取灰度图像和rgb图像叠加_DLANDML的博客-CSDN博客 ......
  • C# OpenCvSharp 图像校正
    效果Demo下载  代码usingSystem;usingSystem.Collections.Generic;usingSystem.ComponentModel;usingSystem.Data;usingSystem.Drawing;usingSystem.Linq;usingSystem.Text;usingSystem.Windows.Forms;usingOpenCvSharp;usingOpenCvSharp.Extensions;namesp......
  • 未来的LibreOffice版本将允许导入和导出APNG图像
    导读文档基金会已经完成了其LibreOffice开源办公套件在2023年谷歌夏季代码(GSoC)中的项目选择,承诺将提供用户要求已久的新功能和改进。未来的LibreOffice版本将允许你导入和导出APNG(AnimatedPNG)图像,这是一种向后兼容PNG图像格式的动画格式,支持比GIF图像更多的颜色和部分透......
  • VisionPro学习笔记(2)——图像转换工具ImageCovertTool
    众所周知,VisionPro是一款功能强大的机器视觉软件,用于开发和部署机器视觉应用程序。其中ImageConvertTool是其中一个重要的工具,用于图像转换和处理。本文将介绍如何使用ImageConvertTool进行图像转换,并探讨其背后的原理。写之前先吐槽一下,引出自己的原因,哈哈哈(当然一个小......
  • 【图像隐藏】基于DCT的数字图像水印防伪附matlab代码
    ✅作者简介:热爱科研的Matlab仿真开发者,修心和技术同步精进,matlab项目合作可私信。......
  • OpenCV
    OpenCV是一个广泛使用的计算机视觉库,可以用于图像和视频处理、目标检测、人脸识别、机器学习等领域。以下是使用OpenCV的简单步骤:安装OpenCV库:您可以使用pip命令在Python环境中安装OpenCV库,例如: Copypipinstallopencv-python导入OpenCV库:在Python脚本中导入OpenCV......