超像素概念是2003年Xiaofeng Ren提出和发展起来的图像分割技术,它是指具有相似纹理、颜色、亮度等特征的相邻像素构成的有一定视觉意义的不规则像素块。它利用像素之间特征的相似性将像素分组,用少量的超像素代替大量的像素来表达图片特征,很大程度上降低了图像后处理的复杂度,所以通常作为分割算法的预处理步骤。该技术已经被广泛的应用到图像分割、姿势估计、目标跟踪、目标识别等多个计算机视觉任务等。下图展示了几种不同的超像素分割算法的分割结果。
# coding=utf-8
# 导入相应的python包
import argparse
from skimage import io
import matplotlib.pyplot as plt
from skimage.segmentation import slic
from skimage.util import img_as_float
from skimage.segmentation import mark_boundaries
# 设置并解析参数
ap = argparse.ArgumentParser()
ap.add_argument("-i", "--image", required = True, help = "Path to the image")
args = vars(ap.parse_args())
# 读取图片并将其转化为浮点型
image = img_as_float(io.imread(args["image"]))
# 循环设置不同的超像素组
for numSegments in (100, 200, 300):
# 应用slic算法并获取分割结果
segments = slic(image, n_segments = numSegments, sigma = 5)
# 绘制结果
fig = plt.figure("Superpixels -- %d segments" % (numSegments))
ax = fig.add_subplot(1, 1, 1)
ax.imshow(mark_boundaries(image, segments))
plt.axis("off")
# 显示结果
plt.show()
上图展示了SLIC超像素分割算法的分割结果。上图展示了两个测试图片的效果,第1行表示的是原始的输入图片;第2行表示的是设置了100个超像素组的分割结果;第2行表示的是设置了200个超像素组的分割结果;第3行表示的是设置了300个像素的分割结果。通过上面的结果我们可以获得一些信息,即通过超像素分割我们可以将整个图像划分为含有固定个超像素组的感知块,具体如图中的黄色块所示。
%% Clean up
clear all
close all
clc
%Generate image
img = imread('test.jpg');
img = double(rgb2gray(img));
%Invert circle brightness
img = abs(img-1);
%Blur original image with Gaussian kernel with a blur width (standard
%deviaion) of 0.9 pixels
BlurGaussian = 0.9;
G = fspecial('Gaussian',5,BlurGaussian);
img = imfilter(img,G,'replicate');
%Blurring occurs from quantization and from Gaussian
BlurQuantization = 1/sqrt(12);
BlurWidth = sqrt( BlurQuantization^2 + BlurGaussian^2);
%% Create mask
%Only consider edges on columns 35-50
M = true(size(img));
%% Perform edge localization
%Get pixel-level edges with Sobel operator
[E] = edge(img,'sobel');
%Refine to subpixel accuracy
edges = SubpixelEdge(img,E,BlurWidth,M);
%% Plot results
%Show image
figure(1);
imshow(uint8(img)),hold on, axis on;
plot(edges.u,edges.v,'co')
figure(2);
imshow(uint8(M)),hold on, axis on;
plot(edges.u,edges.v,'co')
% p1 = [edges.u(1), edges.v(1), 0];
% p2 = [edges.u(100), edges.v(100), 0];
% p3 = [edges.u(500), edges.v(500), 0];
% p = CircleCenter(p1, p2, p3);
%
% disp('当前圆的半径为%d', p);
x=edges.u;
y=edges.v;
[R,x0,y0]=circ(x,y,edges.NumPts-1);
disp(['第一个圆的半径是: ' num2str(R),' mm' ]);
disp(['第一个圆的圆心坐标:( ' num2str(x0) ,',',num2str(y0),')']);
plot(x0, y0, 'gx');
上图展示了超像素边缘检测的结果。第1行表示的是原始的输入图像;第2行表示的是超像素检测的结果,蓝色表示超像素块,整个结果是叠加在原始图像上面的,我们可以发现超像素可以准确的检测出齿轮的边缘信息,包括它的内环和外环信息;第3行含表示的是单纯的超像素检测结果,整个结果叠加在一个全黑的图像中,中心的绿色的x表示整个圆环的中心点,上述的代码可以计算出圆环的中心和半径值,这在机器视觉领域中具有较多的应用。
对于图中的齿轮而言,我们一般会对该齿轮的外半径、内半径、模数和齿数目比较感兴趣。那么如何通过算法来获取到这些参数,聪明的你肯定能想出一些比较好的方案。
[1] 参考资料