利用几种颜色量化方法提取图片颜色色调

发布于:2022-12-25 ⋅ 阅读:(820) ⋅ 点赞:(0)

利用几种颜色量化方法提取图片颜色色调

这里主要用3种方法:包含两种k-means方法和一种matlab自带的最小方差量化方法。
为了方便对比,文中选用梵高的星空(The Starry Night)作为提取图片。

1 k-means方法(在RGB空间)

颜色量化是指一个减少在图像中的颜色数量的压缩过程。旨在用尽可能少的颜色去还原图片。
所以,也可以用聚类方法去进行处理,即将所有颜色在色彩空间上分布开,然后为每个集群选择所代表的点来创建调色板。

比如梵高的星空:
在这里插入图片描述
把所有像素点的颜色在RGB空间显示出来,可以得到:
在这里插入图片描述

这时我们再利用k-means聚类算法把调色板设为4种颜色,即N=4,
得到像素的局聚类表示为
在这里插入图片描述
质心颜色的连线图如下:
在这里插入图片描述
得到的N=4下的图片为
在这里插入图片描述
可以看到有较大的偏差。
当取N=20时,得到的图为:
在这里插入图片描述
颜色质量要比只用4个颜色的要高出很多。

而在颜色板的分布这张图上,也可以比较明显的看到梵高在做这幅画时使用的主要3种颜色,和wiki百科中提到的ultramarine 、cobalt blue 和indian yellow比较吻合。

2 k-means方法(Lab颜色空间)

事实上,在相同的方法,采用不同的颜色空间进行聚类,可以发现影响最主要的还是数量的选取。可能有些情况下Lab或者HSV方法比RGB看上去更好,但是影响也不是很大。

下图是利用LAB颜色空间进行聚类分析的结果,N=4,并且为了方便对比,将结果依然显示在RGB的坐标系内。
在这里插入图片描述
可以看到结果和第一节的相似。

当N=20的时候,观察和第一节的区别,发现只是在一些细节上划分区域有所差别,基本效果很接近。在这里插入图片描述

3 最小方差量化方法rgb2ind()

matlab中有专门的函数用来进行色彩量化,为rgb2ind(),采用的方法为最小方差量化方法。具体可以参见:
https://ww2.mathworks.cn/help/matlab/ref/rgb2ind.html
这里依然取N=4和N=20进行对比。
在这里插入图片描述
可以看到用matlab自带的方法要比kmeans方法更好。

4 其余名画

在这里插入图片描述

5 代码

K-Means算法用的是matlab里自带的kmeans函数,可以参见:
http://www.mathworks.com/help/stats/kmeans.html
颜色板分布画的连接图用的算法来源于 Python 平面上的点的最短连线网 这篇文章:
https://blog.csdn.net/lnotime/article/details/82313355
LAB和RGB之间的转换用的是 色彩空间Lab和RGB互转的Matlab代码 这篇文章:
https://blog.csdn.net/wendy260310/article/details/17100497

这里由于篇幅,我就只粘贴Kmeans-LAB算法的程序和rgb2ind程序。

clear 
clc

N=20;%设置聚类数目
data = imread('xingkong.JPEG');
dataLAB=single(zeros(size(data)));
[dataLAB(:,:,1),dataLAB(:,:,2),dataLAB(:,:,3)] = RGB2Lab(data(:,:,1),data(:,:,2),data(:,:,3));
hs=size(data);
data2=zeros(hs(1)*hs(2),3);
ii=0;
for j=1:hs(1)
    for k=1:hs(2)
        ii=ii+1;
        data2(ii,:)=dataLAB(j,k,:);
    end
end

XLAB=single(data2);


[idx,CLAB] = kmeans(XLAB,N,'Distance','cityblock','Replicates',5);
C=zeros(size(CLAB));
X=zeros(size(XLAB));
[C(:,1),C(:,2),C(:,3)]=Lab2RGB(CLAB(:,1),CLAB(:,2),CLAB(:,3));
[X(:,1),X(:,2),X(:,3)]=Lab2RGB(XLAB(:,1),XLAB(:,2),XLAB(:,3));
X=X*256;
C=C*256;

figure%原图
set(gcf,'unit','centimeters','position',[10,10,8,7])
image(data);
%三维绘图
figure
set(gcf,'unit','centimeters','position',[10,10,8,7])
hold on
%'MarkerFaceColor'
for j=1:N
    %plot(X(idx==j,1),X(idx==j,2),'LineStyle','none','Marker','.','MarkerSize',12)
    plot3(X(idx==j,1),X(idx==j,2),X(idx==j,3),'LineStyle','none','Marker','.','MarkerSize',12,'MarkerFaceColor',C(j,:)/256,'MarkerEdgeColor',C(j,:)/256);
end
%plot3(C(:,1),C(:,2),C(:,3),'kx','MarkerSize',15,'LineWidth',3) 
view(3)
hold off


%然后输出这几个基准色对应的图
data2_2=single(data2);

j=1:length(idx);
data2_2(j,:)=C(idx(j),:);

ii=0;
for j=1:hs(1)
    for k=1:hs(2)
        ii=ii+1;
        data(j,k,:)=data2_2(ii,:);
    end
end
figure%新图
set(gcf,'unit','centimeters','position',[10,10,8,7])
image(data);

figure%点线图
set(gcf,'unit','centimeters','position',[10,10,8,7])
paths=find_min_length_3D(C);%参见:平面上的点的最短连线网
hold on
for j=1:size(paths,1)
    plot3(paths(j,[1,4]),paths(j,[2,5]),paths(j,[3,6]),'b-')
    plot3(C(j,1),C(j,2),C(j,3),'LineStyle','none','Marker','.','MarkerSize',40,'MarkerFaceColor',C(j,:)/256,'MarkerEdgeColor',C(j,:)/256)
end
plot3(C(j+1,1),C(j+1,2),C(j+1,3),'LineStyle','none','Marker','.','MarkerSize',40,'MarkerFaceColor',C(j,:)/256,'MarkerEdgeColor',C(j+1,:)/256)
hold off
view(3)

rgb2ind程序

clear
N=20;
%设置图像位数
RGB = imread('Stacks of wheat.jpg');
figure
set(gcf,'unit','centimeters','position',[10,10,8,7])
imagesc(RGB)

[IND,map] = rgb2ind(RGB,N);
IND=IND+1;
figure
set(gcf,'unit','centimeters','position',[10,10,8,7])
imagesc(IND)
colormap(map)


%三维绘图
hs=size(RGB);
data1=reshape(RGB,hs(1)*hs(2),3);
IND1=reshape(IND,hs(1)*hs(2),1);


figure
set(gcf,'unit','centimeters','position',[10,10,8,7])
hold on
for j=1:N
    plot3(data1(IND1==j,1),data1(IND1==j,2),data1(IND1==j,3),'LineStyle','none','Marker','.','MarkerSize',12,'MarkerEdgeColor',map(j,:));
end
view(3)
hold off


figure%绘制连线图
set(gcf,'unit','centimeters','position',[10,10,8,7])
paths=find_min_length_3D(map);
hold on
for j=1:size(paths,1)
    plot3(paths(j,[1,4]),paths(j,[2,5]),paths(j,[3,6]),'b-')
    plot3(map(j,1),map(j,2),map(j,3),'LineStyle','none','Marker','.','MarkerSize',40,'MarkerEdgeColor',map(j,:))
end
plot3(map(j+1,1),map(j+1,2),map(j+1,3),'LineStyle','none','Marker','.','MarkerSize',40,'MarkerEdgeColor',map(j+1,:))

hold off
view(3)


find_min_length_3D函数

function paths=find_min_length_3D(pots)
%输入单,返回最短连接网格
%pots满足N行3列的格式

N=size(pots,1);
%初始化
con=pots(1,:);%已经连线的点集,先随便放一个点进去
Ncon=pots(2:end,:);%还没连线的点集
paths=zeros(N-1,6);%所有连线

length_total=0;%总长度
%循环
for j=1:N-1
    potA=con(1,:);
    potB=Ncon(1,:);
    lengthAB=sum((potA-potB).^2);
    for m=1:size(con,1)
        for n=1:size(Ncon,1)
            lengthAB_temp=sum((con(m,:)-Ncon(n,:)).^2);
            if lengthAB_temp<lengthAB
                lengthAB=lengthAB_temp;%如果新线段更短,则采用新的线段
                potA=con(m,:);
                potB=Ncon(n,:);
            end
        end
    end
    paths(j,:)=[potA,potB];
    con=[con;potB];
    Ncon(sum(Ncon==potB,2)==3,:)=[];%这里3D所以是3
    length_total=length_total+lengthAB;
end
end

本文含有隐藏内容,请 开通VIP 后查看