使用Python和OpenCV标记超级像素的炫彩度

使用Python和OpenCV标记超级像素的炫彩度

这篇博客将介绍如何使用SLIC分割算法来计算输入图像的超像素,并对每一块超像素区域计算炫彩度量值。然后将每个区域的炫彩度量值加入到掩模图像,以展示图像的最丰富多彩和最不丰富多彩的区域;
并将掩模图像叠加透明层到原始图像上。

1. 效果图

原始图 VS 超像素蒙版图 VS 叠加效果图 如下:小区里的粉色木兰花,挺娇俏的一小朵,并没有完整绽开,却不影响它好看。

从下图可以很容易看出颜色暗的地方是最不炫彩的区域,图中的浅色区域是最炫彩的区域。默认超像素分割100块,距离花朵是最炫彩的,花朵下部的天空背景是最不炫彩的区域。
在这里插入图片描述
超像素分割10块,效果图如下:
在这里插入图片描述

效果图2,同样是小区里的花,这一次是绽放的青木兰,拍自去年疫情期间。
在这里插入图片描述
效果图3:超像素分割设置为5块。 可以清楚的看到,中间的蒙版图分了5块超像素区域,中间颜色最深的白色花朵是最不鲜艳的区域。
在这里插入图片描述

2. 步骤

首先可以将滑动窗口应用于循环图像并计算每个ROI的炫彩度量分数。甚至可以应用图像金字塔,如果需要在多个尺度上计算特定区域的彩色度,也可以应用图像金字塔。

  • 将Superpixel分段应用于输入图像。
  • 单独循环每个超像素,并计算它们各自的彩色分数。
  • 维护包含每个超像素的彩色分数的掩模。
  • 基于此mask,可以可视化图像的最彩色区域。更丰富多彩的图像的区域将具有更大的彩色度量分数,而那些较不炫彩的区域将拥有更小的值。
  1. 应用SLIC算法从输入图像中提取超像素;
  2. 遍历每个超像素,并分别计算炫彩度量值;
  3. 叠加超像素透明层到原始图像上并展示;

3. 源代码

# USAGE
# python colorful_regions.py --image images/flower.jpg
# 超像素划分只划分为4块
# python colorful_regions.py --image images/flower.jpg -s 5

# 导入必要的包
from skimage.exposure import rescale_intensity
from skimage.segmentation import slic  # 切片函数计算超像素
from skimage.util import img_as_float
from skimage import io
import numpy as np
import argparse
import cv2
import imutils


# 超像素区域计算炫彩度
def segment_colorfulness(image, mask):
    # 将图像分离为相对的RGB分量
    # 然后构建每一个分量的蒙版,计算蒙版区域的统计值
    (B, G, R) = cv2.split(image.astype("float"))
    R = np.ma.masked_array(R, mask=mask)
    G = np.ma.masked_array(G, mask=mask)
    B = np.ma.masked_array(B, mask=mask)

    # 计算 rg = R - G
    rg = np.absolute(R - G)
    # 计算 yb = 0.5 * (R + G) - B
    yb = np.absolute(0.5 * (R + G) - B)

    # 构建 rg、yb的均值和标准偏差
    stdRoot = np.sqrt((rg.std() ** 2) + (yb.std() ** 2))
    meanRoot = np.sqrt((rg.mean() ** 2) + (yb.mean() ** 2))

    # 计算“炫彩度”并返回
    return stdRoot + (0.3 * meanRoot)


# 构建命令行参数及解析
# --image 输入图像路径
# --segments 分离超像素个数,默认100,该值越小,较大的超像素越大,允许算法运行得更快。段的数量越大,分割更细粒度,但SLIC需要更长时间运行(由于需要计算更多的集群)。
ap = argparse.ArgumentParser()
ap.add_argument("-i", "--image", required=True,
                help="path to input image")
ap.add_argument("-s", "--segments", type=int, default=100,
                help="# of superpixels")
args = vars(ap.parse_args())

# 使用opencv加载图像,然后展示,开辟空间以展示超像素炫彩度可视化
orig = cv2.imread(args["image"])
orig = imutils.resize(orig, width=300)
vis = np.zeros(orig.shape[:2], dtype="float")

# 加载图像,使用scikit-image的SLIC超像素分割方法
image = io.imread(args["image"])
image = imutils.resize(image, width=300)
# -- 图像
# -- 分段数
# -- True 使用原始的不修改任何原始参数的SLIC超像素分割算法
segments = slic(img_as_float(image), n_segments=args["segments"],
                slic_zero=True)

# 循环遍历每一个独立的超像素
for v in np.unique(segments):
    # 对分段构建蒙版,并计算统计
    mask1 = np.ones(image.shape[:2])
    mask = np.ones(image.shape[:2])
    mask[segments == v] = 0
    # cv2.imshow("image VS mask VS mask1", np.hstack([mask1, mask]))
    # cv2.waitKey(0)

    # 计算超像素炫彩度,更新可视化数组
    C = segment_colorfulness(orig, mask)
    vis[segments == v] = C

# 将像素浮点数值重新缩放到典型的8位无符号整数[0-255]数组,以使用opencv展示图像
vis = rescale_intensity(vis, out_range=(0, 255)).astype("uint8")

# 叠加超像素炫彩度到原始图像中,透明度为0.6
alpha = 0.6
overlay = np.dstack([vis] * 3)
output = orig.copy()
cv2.addWeighted(overlay, alpha, output, 1 - alpha, 0, output)

# 展示输出图像
cv2.imshow("Input", orig)
cv2.imshow("Visualization", vis)
cv2.imshow("Output", output)
cv2.waitKey(0)

参考

猜你喜欢

转载自blog.csdn.net/qq_40985985/article/details/115012617
今日推荐