MATLAB | 如何自然好看的从图片中提取颜色并制作色卡

news2025/1/17 21:38:15

在这里研究了一下各种排序算法,写一篇如何由图片一键生成颜色条的方法。


1 关于大量颜色排序

假设有大量颜色怎么对其进行排序呢,首先想到的最简单方法就是将其按照RGB值的大小进行排序,为了方便展示颜色条,这里编写了一个颜色条展示函数:

function showCM(CList)
if nargin<1,CList=winter();end
fig=figure('Units','normalized','Position',[0,50/100,1,7/100]); 
ax=gca(fig);hold on
ax.XLim=[0,1];
ax.YLim=[0,1];
ax.Position=[0,0,1,1];
ax.XColor='none'; 
ax.YColor='none';
C=[];
C(:,:,1)=repmat([CList(:,1)',nan],[2,1]);
C(:,:,2)=repmat([CList(:,2)',nan],[2,1]);
C(:,:,3)=repmat([CList(:,3)',nan],[2,1]);
[XMesh,YMesh]=meshgrid(linspace(0,1,size(CList,1)+1),[0,1]);
surface(XMesh,YMesh,XMesh.*0,'CData',C,'EdgeColor','none');
end

假设对于RGB颜色,先按照R通道数值进行排序,R相同时通过G通道进行排序,G通道相同时通过B通道进行排序,即以[R,G,B]为排序依据时:

[R,G,B]=meshgrid(0:15:255,0:15:255,0:15:255);
CList=[R(:),G(:),B(:)]./255;

[~,ind]=sortrows(CList,[1,2,3]);  
NCList=CList(ind,:);

showCM(NCList)


展示一下其他排序依据时的排序结果:
[R,B,G]

[G,R,B]

[G,B,R]

[B,R,G]

[B,G,R]

只能说都排得一般,要么断断续续,要么一段一段的。考虑加入灰度影响:

[R,G,B]=meshgrid(0:15:255,0:15:255,0:15:255);
CList=[R(:),G(:),B(:)]./255;

Gy=rgb2gray(reshape(CList,[],1,3));
[~,ind]=sortrows([CList,Gy],[4,2,3,1]);  
NCList=CList(ind,:);

showCM(NCList)


大局上看起来还不错不过细节上颜色变化更剧烈更不连续了。。。那考虑一下HSV空间呢?

[R,G,B]=meshgrid(0:15:255,0:15:255,0:15:255);
CList=[R(:),G(:),B(:)]./255;

hsvList=rgb2hsv(CList);
[~,ind]=sortrows(hsvList,[1,2,3]);  
NCList=CList(ind,:);

showCM(NCList)

[H,S,V]

[H,V,S]

[S,H,V]

[S,V,H]

[V,H,S]

[V,S,H]

可以看到大部分排序都是整体还凑活但是局部非常不连续,有没有啥局部比较连续的算法呢?

我们很容易想到旅行商算法,但是旅行商算法求解困难,这里使用由Alan Zucconi提出来的近似于最小生成书生成过程的旅行商算法,就像最小生成树一样不断把最近的点加入树中,但是生成的结果没有树枝:

function NCList=NTraveler(CList)
% 想法来自: Alan Zucconi
N=size(CList,1);
NCList=zeros(N,3);
ind=find(sum(CList,2)==min(sum(CList,2)),1);
NCList(1,:)=CList(ind,:);
CList(ind,:)=[];
for i=2:N
    lastColor=NCList(i-1,:);
    normList=vecnorm((lastColor-CList)');
    ind=find(normList==min(normList),1);
    NCList(i,:)=CList(ind,:);
    CList(ind,:)=[];
end
end

使用该算法排序:

[R,G,B]=meshgrid(0:15:255,0:15:255,0:15:255);
CList=[R(:),G(:),B(:)]./255;

NCList=NTraveler(CList);

showCM(NCList)

这样整体比较乱但局部比较连续,毕竟我们造colormap的时候不可能几万个颜色甚至几十万个颜色去构造,肯定是取几个颜色进行插值。


2 颜色聚类

首先我写了个聚类结果展示函数:

function showCluster(ColorList,index,C)
colorNum=size(C,1);C=round(C);
RGBList=double(ColorList);
ax=gca;hold on;grid on;view(3)
STR{colorNum}='';
for i=1:colorNum
    scatter3(RGBList(index==i,1),RGBList(index==i,2),RGBList(index==i,3),...
        'filled','CData',C(i,:)./255);
    STR{i}=[num2str(C(i,1)),' ',num2str(C(i,2)),' ',num2str(C(i,3))];
end 
legend(STR,'Color',[0.9412 0.9412 0.9412],'FontName','Cambria','LineWidth',0.8,'FontSize',11,'Location','best')
ax.GridLineStyle='--';
ax.LineWidth=1.2;
ax.XLabel.String='R channel';
ax.XLabel.FontSize=13;
ax.XLabel.FontName='Cambria';
ax.YLabel.String='G channel';
ax.YLabel.FontSize=13;
ax.YLabel.FontName='Cambria';
ax.ZLabel.String='B channel';
ax.ZLabel.FontSize=13;
ax.ZLabel.FontName='Cambria';
end

这里给出两种算法的对比,一种就是直接kmeans聚类,另一种是使用MATLAB自带函数rgb2ind进行聚类,其中rgb2ind函数会快得多。

oriPic=imread('gallery\1.jpg');
colorNum=9;

% kmeans聚类
RGBList=double(reshape(oriPic,prod(size(oriPic,[1,2])),3));
[index,C]=kmeans(RGBList,colorNum,'Distance','sqeuclidean','MaxIter',1000,'Display','iter');

showCluster(RGBList,index,C)
showCM(C./255)

figure()
% rgb2ind聚类
RGBList=double(reshape(oriPic,prod(size(oriPic,[1,2])),3));
[index,C]=rgb2ind(oriPic,colorNum);
index=index(:)+1;C=C.*255;

showCluster(RGBList,index,C)
showCM(C./255)

示例1


kmeans


rgb2ind

示例2


kmeans


rgb2ind

示例3


kmeans


rgb2ind

可以看到两种方法聚类结果相差不大,但rgb2ind方法却快非常多。


3 少量颜色排序

降维法,类似于PCA降维法,要找到数据的主方向,之后将数据映射到主方向上来排序,以下是降维法和旅行商法对比:

oriPic=imread('gallery\1.jpg');   
colorNum=8;

RGBList=double(reshape(oriPic,prod(size(oriPic,[1,2])),3));
[~,C]=rgb2ind(oriPic,colorNum);
% 降维法
C0=C-mean(C); 
covMat=cov(C0);
[V,~]=eigs(covMat,1); 
[~,ind]=sort(C0*V);
C=C(ind,:);
showCM(C)

% 旅行商法
C=NTraveler(C); 
showCM(C)

示例1


降维法

旅行商法

示例2


降维法

旅行商法

示例3


降维法

旅行商法

示例4


降维法

旅行商法

可以看到在色调比较简单时两种方法结果类似,但在色调比较复杂时,旅行商算法效果较好。


4 色卡直接生成

写了段代码,稍微改改颜色数量,再改改图片链接就能自动生成色卡:

oriPic=imread('gallery\1.jpg');    
colorNum=8;                
RGBList=double(reshape(oriPic,prod(size(oriPic,[1,2])),3));
[~,C]=rgb2ind(oriPic,colorNum);
C=NTraveler(C); 
disp(C)

[M,N,~]=size(oriPic);
if N>M
    for i=1:colorNum
        oriPic(M+1:M+round(M/6),1+(round((N-1)*(i-1)/colorNum):round((N-1)*i/colorNum)),1)=C(i,1).*255;
        oriPic(M+1:M+round(M/6),1+(round((N-1)*(i-1)/colorNum):round((N-1)*i/colorNum)),2)=C(i,2).*255;
        oriPic(M+1:M+round(M/6),1+(round((N-1)*(i-1)/colorNum):round((N-1)*i/colorNum)),3)=C(i,3).*255;
    end
else
    for i=1:colorNum
        oriPic(1+(round((M-1)*(i-1)/colorNum):round((M-1)*i/colorNum)),N+1:N+round(N/6),1)=C(i,1).*255;
        oriPic(1+(round((M-1)*(i-1)/colorNum):round((M-1)*i/colorNum)),N+1:N+round(N/6),2)=C(i,2).*255;
        oriPic(1+(round((M-1)*(i-1)/colorNum):round((M-1)*i/colorNum)),N+1:N+round(N/6),3)=C(i,3).*255;
    end
end
imshow(oriPic)


5 颜色插值

写了个简单函数进行插值:

function CM=interpColor(CList,n)
Ci=1:size(CList,1);
Cq=linspace(1,size(CList,1),n);
CM=[interp1(Ci,CList(:,1),Cq,'pchip')',...
    interp1(Ci,CList(:,2),Cq,'pchip')',...
    interp1(Ci,CList(:,3),Cq,'pchip')'];
end

就举个简单的例子:

oriPic=imread('gallery\1.jpg');        
colorNum=8;

% 获取配色
RGBList=double(reshape(oriPic,prod(size(oriPic,[1,2])),3));
[~,C]=rgb2ind(oriPic,colorNum);
C=NTraveler(C); 
showCM(C)
% 插值
CM=interpColor(C,256);
showCM(CM)




6 实际应用

实际从图片取色用在绘图中:

oriPic=imread('gallery\12.jpg');        
colorNum=8;

% 获取配色
RGBList=double(reshape(oriPic,prod(size(oriPic,[1,2])),3));
[~,C]=rgb2ind(oriPic,colorNum);
C=NTraveler(C); 
% 插值
CM=interpColor(C,256);

fig=gcf;
fig.Position=[200,200,800,600];
% 原图像
ax1=axes('Parent',fig,'Position',[0,1/2,1/2,1/2]+[1/20,1/20,-1/15,-1/15]);
ax1.NextPlot='add';axis tight
ax1.FontName='Cambria';
ax1.XColor='none';
ax1.YColor='none';
[M,N,~]=size(oriPic);
if N>M
    for i=1:colorNum
        oriPic(M+1:M+round(M/6),1+(round((N-1)*(i-1)/colorNum):round((N-1)*i/colorNum)),1)=C(i,1).*255;
        oriPic(M+1:M+round(M/6),1+(round((N-1)*(i-1)/colorNum):round((N-1)*i/colorNum)),2)=C(i,2).*255;
        oriPic(M+1:M+round(M/6),1+(round((N-1)*(i-1)/colorNum):round((N-1)*i/colorNum)),3)=C(i,3).*255;
    end
else
    for i=1:colorNum
        oriPic(1+(round((M-1)*(i-1)/colorNum):round((M-1)*i/colorNum)),N+1:N+round(N/6),1)=C(i,1).*255;
        oriPic(1+(round((M-1)*(i-1)/colorNum):round((M-1)*i/colorNum)),N+1:N+round(N/6),2)=C(i,2).*255;
        oriPic(1+(round((M-1)*(i-1)/colorNum):round((M-1)*i/colorNum)),N+1:N+round(N/6),3)=C(i,3).*255;
    end
end
image(flipud(oriPic))
% 气泡图
ax2=axes('Parent',fig,'Position',[1/2,1/2,1/2,1/2]+[1/20,1/20,-1/15,-1/15]);
ax2.NextPlot='add';grid on
ax2.GridLineStyle=':';
ax2.XMinorTick='on';
ax2.YMinorTick='on';
ax2.FontName='Cambria';
ax2.LineWidth=.7;
x=1:30;
[~,ind]=sort(rand(1,30));
x=x(ind);
y=rand(1,30);
sz=sort(rand(1,30));
bubblechart(x,y,sz,'CData',1:30);
colormap(ax2,CM)
% 折线图
ax3=axes('Parent',fig,'Position',[0,0,1/2,1/2]+[1/20,1/20,-1/15,-1/15]);
ax3.NextPlot='add';
t=linspace(0,5*pi,200);
C70=interpColor(C,70);
for i=1:70
    plot(t,sin(t+i.^2./700)./(10+i).*20+i.*.1,'Color',C70(i,:),'LineWidth',2);
end
% 坐标区域修饰
ax3.YLim=[0,7];
ax3.XLim=[0,5*pi];
ax3.YTick=0:.5:5;
ax3.XTick=0:1:15;
ax3.YGrid='on';
ax3.GridLineStyle='-.';
ax3.LineWidth=1;
ax3.XMinorTick='on';
ax3.YMinorTick='on';
ax3.Box='on';
ax3.FontName='Cambria';
ax3.FontSize=11;
% 曲面图
ax4=axes('Parent',fig,'Position',[1/2+1/50,0,1/2,1/2]);
ax4.NextPlot='add';grid on
ax4.Projection='perspective';
ax4.LineWidth=.8;
ax4.XMinorTick='on';
ax4.YMinorTick='on';
ax4.ZMinorTick='on';
ax4.GridLineStyle=':';
ax4.ZLim=[0,90];
ax4.FontName='Cambria';
view(-37,42) 
X=linspace(0,1,100)';
CL=(-cos(X*2*pi)+1).^.2;
r=(X-.5)'.^2+(X-.5).^2;
Z=abs(ifftn(exp(7i*rand(100))./r.^.9)).*(CL*CL')*30;
surf(X,X.',Z,'EdgeColor',[.9,.9,.9],'EdgeAlpha',.1)
colormap(ax4,CM);


7 算法的进一步应用

我之前用App designer 制作过一款是色卡生成器,正好今天用文章所示算法改进一下:

Load Img(导入图片) -> 选择颜色数颜色格式 -> 点击RUN运行

之后可以点击图示处存储色卡:

色卡生成效果:

该工具完整代码:

function colourAtla
% @author slandarer

% 颜色数量
colorNum=2;% 初始颜色列表
colorList=[189  115  138; 237  173  158
           140  199  181; 120  205  205
            79  148  205; 205  150  205]; 
% 颜色格式
% [0 1]   -> 1
% [0 255] -> 2
% #hex    -> 3
% hsv     -> 4
colorType=3;
% 三维图片矩阵
oriPic=[];
% RGB数据列
RGBList=[];
% =========================================================================
% figure窗口构建
atlaFig=uifigure('units','pixels');
atlaFig.Position=[10,65,750,500];
atlaFig.NumberTitle='off';
atlaFig.MenuBar='none';
atlaFig.Name='colour atla 1.0 | by slandarer';
atlaFig.Color=[1,1,1];
atlaFig.Resize='off';
% 显示图像axes区域
imgAxes=uiaxes('Parent',atlaFig);
imgAxes.Position=[10,10,480,480];
imgAxes.XLim=[0,100];
imgAxes.YLim=[0,100];
imgAxes.XTick=[];
imgAxes.YTick=[];
imgAxes.Box='on';
imgAxes.Toolbar.Visible='off';
% 显示色卡axes区域
atlaAxes=uiaxes('Parent',atlaFig);
atlaAxes.Position=[500,90,240,400];
atlaAxes.XLim=[0,240];
atlaAxes.YLim=[0,400];
atlaAxes.XTick=[];
atlaAxes.YTick=[];
atlaAxes.Box='on';
atlaAxes.Toolbar.Visible='on';
hold(atlaAxes,'on')
% 重绘色卡函数
function freshColorAtla(~,~)
    hold(atlaAxes,'off')
    plot(atlaAxes,[-1,-1],[-1,-1]);
    hold(atlaAxes,'on')
    text(atlaAxes,10,370,'Colour Atla','FontName','Cambria','FontSize',21);
    for i=1:size(colorList,1)
        fill(atlaAxes,[10 120 120 10],[370 370 390 390]-50-28*(i-1),colorList(i,:)./255)
        switch colorType
            case 1 % 显示RGB [0 1]格式颜色数据
                tempColorR=sprintf('%.2f',colorList(i,1)./255);
                tempColorG=sprintf('%.2f',colorList(i,2)./255);
                tempColorB=sprintf('%.2f',colorList(i,3)./255);
                text(atlaAxes,133,330-28*(i-1),...
                    [tempColorR,' ',tempColorG,' ',tempColorB],...
                    'FontName','Cambria','FontSize',16);
            case 2 % 显示RGB[0 255]格式颜色数据
                text(atlaAxes,135,330-28*(i-1),...
                    [num2str(colorList(i,1)),' ',...
                     num2str(colorList(i,2)),' ',...
                     num2str(colorList(i,3))],...
                    'FontName','Cambria','FontSize',16);
            case 3 % 显示16进制格式颜色数据
                exchange_list={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
                tempColor16='#';
                for ii=1:3
                    temp_num=colorList(i,ii);
                    tempColor16(1+ii*2-1)=exchange_list{(temp_num-mod(temp_num,16))/16+1};
                    tempColor16(1+ii*2)=exchange_list{mod(temp_num,16)+1};
                end
                text(atlaAxes,135,330-28*(i-1),tempColor16,'FontName','Cambria','FontSize',16);
            case 4 % 显示hsv格式颜色数据
                [h,s,v]=rgb2hsv(colorList(i,1),colorList(i,2),colorList(i,3));
                text(atlaAxes,130,330-28*(i-1),...
                    [sprintf('%.2f',h),'  ',...
                     sprintf('%.2f',s),'  ',...
                     num2str(v)],...
                     'FontName','Cambria','FontSize',16);
        end
    end
    outputData()
end
freshColorAtla()
% =========================================================================
% 选择k-means k值按钮(颜色数量按钮)
uilabel('parent',atlaFig,'Text','  ColorNum','FontName','Cambria','FontWeight','bold',...
    'FontSize',15,'BackgroundColor',[0.31 0.58 0.80],'position',[500,50,80,25],'FontColor',[1 1 1]);
CNsetBtn=uispinner(atlaFig,'Value',2,'limit',[2 12],'FontName','Cambria','Step',1,...
    'ValueDisplayFormat','%.f','FontSize',14,'ValueChangedFcn',@CNset,'position',[580,50,50,25]);
function CNset(~,~)% color number set function
    colorNum=CNsetBtn.Value;  
end
% 选择颜色类型按钮
uilabel('parent',atlaFig,'Text','  ColorType','FontName','Cambria','FontWeight','bold',...
    'FontSize',15,'BackgroundColor',[0.31 0.58 0.80],'position',[500,15,90,25],'FontColor',[1 1 1]);
TPsetBtnGp=uidropdown('parent',atlaFig);
TPsetBtnGp.Items={'  [0 1]';'[0 255]';'  #hex';'  HSV'};
TPsetBtnGp.ValueChangedFcn=@TPset;
TPsetBtnGp.Position=[580,15,70,25];
TPsetBtnGp.Value='  #hex';
function TPset(~,~)% color type set function
    switch TPsetBtnGp.Value
        case '  [0 1]',colorType=1;
        case '[0 255]',colorType=2;
        case '  #hex', colorType=3;
        case '  HSV',  colorType=4;
    end
    freshColorAtla()
end

% 导入图片按钮
uibutton(atlaFig,'Text','Load Img','BackgroundColor',[0.59 0.71 0.84],'FontColor',[1 1 1],...
    'FontWeight','bold','Position',[640,50,100,25],'FontName','Cambria','FontSize',15,'ButtonPushedFcn',@LDimg);
function LDimg(~,~)
    try
        [filename, pathname] = uigetfile({'*.jpg;*.tif;*.png;*.gif','All Image Files';...
            '*.*','All Files' });
        oriPic=imread([pathname,filename]);
        [imgXLim,imgYLim,~]=size(oriPic);
        len=max([imgXLim,imgYLim]);
        imgAxes.XLim=[0 len];
        imgAxes.YLim=[0 len];
        hold(imgAxes,'off')
        imshow(oriPic,'Parent',imgAxes)
        RGBList=double(reshape(oriPic,prod(size(oriPic,[1,2])),3));
    catch
    end
end
% 开始聚类按钮
uibutton(atlaFig,'Text','RUN','BackgroundColor',[0.59 0.71 0.84],'FontColor',[1 1 1],...
    'FontWeight','bold','Position',[660,15,80,25],'FontName','Cambria','FontSize',15,'ButtonPushedFcn',@runKmeans);
function runKmeans(~,~)
    [~,C]=rgb2ind(oriPic,colorNum);
    C=round(NTraveler(C).*255);
    colorList=C;
    freshColorAtla()
end
% 命令行输出数据函数
function outputData(~,~)
    disp(['output time:',datestr(now)])
    disp('color list:')
    for i=1:size(colorList,1)
        switch colorType % 与色卡显示类似
            case 1
                tempData(i,:)=roundn(colorList(i,:)./255,-2);
            case 2
                tempData(i,:)=colorList(i,:);
            case 3
                exchange_list={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
                tempColor16='#';
                for ii=1:3
                    temp_num=colorList(i,ii);
                    tempColor16(1+ii*2-1)=exchange_list{(temp_num-mod(temp_num,16))/16+1};
                    tempColor16(1+ii*2)=exchange_list{mod(temp_num,16)+1};
                end
                tempData(i,1)={tempColor16};
            case 4
                [h,s,v]=rgb2hsv(colorList(i,1),colorList(i,2),colorList(i,3));
                tempData(i,:)=[h,s,v];
        end
    end
    disp(tempData);
end
function NCList=NTraveler(CList)
% 想法来自: Alan Zucconi
N=size(CList,1);
NCList=zeros(N,3);
ind=find(sum(CList,2)==min(sum(CList,2)),1);
NCList(1,:)=CList(ind,:);
CList(ind,:)=[];
for i=2:N
    lastColor=NCList(i-1,:);
    normList=vecnorm((lastColor-CList)');
    ind=find(normList==min(normList),1);
    NCList(i,:)=CList(ind,:);
    CList(ind,:)=[];
end
end
end

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/415331.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Pytorch】 理解张量Tensor

本文参加新星计划人工智能(Pytorch)赛道&#xff1a;https://bbs.csdn.net/topics/613989052 这是目录张量Tensor是什么&#xff1f;张量的创建为什么要用张量Tensor呢&#xff1f;总结张量Tensor是什么&#xff1f; 在深度学习中&#xff0c;我们经常会遇到一个概念&#xff…

初探Redis整体架构

文章目录1、Redis为什么选择单线程2、逐步加入多线程3、Redis采用IO多路复用---epoll和Reactor架构4、Redis6/7默认是否开启了多线程&#xff1f;1、Redis为什么选择单线程 这种问法其实并不严谨&#xff0c;为啥这么说呢? Redis几个里程碑式的重要版本 理清一个事实&#…

一文带你安装opencv和常用库(保姆级教程少走80%的弯路)

0.导语 离上一个opencv安装保姆级教程发布已经过去了快一年了&#xff0c;这一年来我收到了来自很多C友的鼓励。打算学opencv的各位朋友都会在安装opencv和各种库过程中浪费掉60%的时间和精力&#xff1b;博主在这一年来尝试各种各样的安装方法&#xff0c;全网搜集各种资料总…

[ 云计算 | Azure ] Chapter 05 | 核心体系结构之管理组、订阅、资源和资源组以及层次关系

本文主要对如下内容进行讲解&#xff1a;Azure云计算的核心体系结构组件中的&#xff1a;资源、订阅和资源组&#xff0c;以及了解 Azure 资源管理器 (ARM) 如何部署资源。 本系列已经更新文章列表&#xff1a; [ 云计算 | Azure ] Chapter 03 | 描述云计算运营中的 CapEx 与…

元宇宙与网络安全

元宇宙是一种虚拟现实空间&#xff0c;用户可以在计算机生成的环境中进行互动。元宇宙的应用范围很广&#xff0c;比如房地产&#xff0c;医疗&#xff0c;教育&#xff0c;军事&#xff0c;游戏等等。它提供了更具沉浸感的体验&#xff0c;更好地现实生活整合&#xff0c;以及…

图像分类算法:ResNet论文解读

图像分类算法&#xff1a;ResNet论文解读 前言 ​ 其实网上已经有很多很好的解读各种论文的文章了&#xff0c;但是我决定自己也写一写&#xff0c;当然&#xff0c;我的主要目的就是帮助自己梳理、深入理解论文&#xff0c;因为写文章&#xff0c;你必须把你所写的东西表达清楚…

游戏工厂:AI(AIGC/ChatGPT)与流程式游戏开发(码客 卢益贵)

关键词&#xff1a;AI&#xff08;AIGC、ChatGPT、文心一言&#xff09;、流程式管理、好莱坞电影流程、电影工厂、游戏工厂、游戏开发流程、游戏架构、模块化开发 一、前言 开发周期长、人工成本高、成功率低等使得游戏公司融资比较困难。有的公司凭一个爆款游戏一骑绝尘之后…

奇异值分解(SVD)和图像压缩

在本文中&#xff0c;我将尝试解释 SVD 背后的数学及其几何意义&#xff0c;还有它在数据科学中的最常见的用法&#xff0c;图像压缩。 奇异值分解是一种常见的线性代数技术&#xff0c;可以将任意形状的矩阵分解成三个部分的乘积&#xff1a;U、S、V。原矩阵A可以表示为&#…

阿里通义千问、百度文心一言、ChatGPT与GPT-4大比拼

各个大模型的研究测试传送门 ​阿里通义千问传送门&#xff1a; https://tongyi.aliyun.com/chat 百度文心一言传送门&#xff1a; https://yiyan.baidu.com/ ChatGPT传送门&#xff08;免墙&#xff0c;可直接注册测试&#xff09;&#xff1a; https://wowchat.cn GPT…

离线安装k8s/kubernetes v1.17.1并部署服务验证功能

条件&#xff1a; 3台没有网络的centos7.9服务器 1.系统优化 hostnamectl set-hostname k8s-master && bash #只在master节点上执行 hostnamectl set-hostname k8s-node1 && bash #只在node1节点上执行 hostnamectl set-hostname k8s-node2 && …

嵌入式:BSP的理解

BSP概念总结BSP定义BSP的特点BSP的主要工作BSP在嵌入式系统和Windowsx系统中的不同BSP和PC机主板上的BIOS区别BSP与 HAL关系嵌入式计算机系统主要由 硬件层&#xff0c;中间层&#xff0c;系统软件层和应用软件层四层组成。硬件层&#xff1a;包含CPU&#xff0c;存储器(SDRAM&…

(数字图像处理MATLAB+Python)第四章图像正交变换-第一节:离散傅里叶变换

文章目录一&#xff1a;一维离散傅里叶变换&#xff08;1&#xff09;定义&#xff08;2&#xff09;实例二&#xff1a;一维快速傅里叶变换&#xff08;1&#xff09;定义&#xff08;2&#xff09;实例三&#xff1a;二维离散傅里叶变换&#xff08;1&#xff09;定义&#x…

SpringCloud微服务技术栈.黑马跟学(十二)

SpringCloud微服务技术栈.黑马跟学 十二今日目标服务异步通信-高级篇1.消息可靠性1.1.生产者消息确认1.1.1.修改配置1.1.2.定义Return回调1.1.3.定义ConfirmCallback1.2.消息持久化1.2.1.交换机持久化1.2.2.队列持久化1.2.3.消息持久化1.3.消费者消息确认1.3.1.演示none模式1.3…

Flutter TextField UI 实例 —— 新手礼包

大家好&#xff0c;我是17。 新手礼包一共 3 篇文章&#xff0c;每篇都是描述尽量详细&#xff0c;实例讲解&#xff0c;包会&#xff01; Flutter Row 实例 —— 新手礼包Flutter TextField UI 实例 —— 新手礼包Flutter TextField 交互实例 —— 新手礼包 本篇介绍了 Tex…

机器学习:基于逻辑回归对超市销售活动预测分析

系列文章目录 作者&#xff1a;i阿极 作者简介&#xff1a;Python领域新星作者&#xff1a;博主个人首页 &#x1f60a;&#x1f60a;&#x1f60a;如果觉得文章不错或能帮助到你学习&#xff0c;可以点赞&#x1f44d;收藏&#x1f4c1;评论&#x1f4d2;关注哦&#xff01;&a…

linxu学习之进程

文章目录进程程序和进程产生进程销毁进程多进程高并发设计孤儿僵尸守护进程孤儿进程&#xff1a;守护进程(重点)僵尸进程&#xff1a;进程 程序和进程 操作系统可以运行多个程序&#xff0c;那他是如何运行的&#xff1f;实际上&#xff0c;CPU的执行是很快的&#xff0c;而待…

《随便测测》WEB接口测试平台

编写用例的船新版本&#xff0c;从未有过的顺滑体验背景在保证用例运行稳定、高效、准确的前提下以降低测试人员编写用例的时间为目的&#xff0c;减少编写用例的复杂度&#xff0c;达到提升效率的目的。解决问题因被测系统业务流程长&#xff0c;接口多&#xff08;多的一个场…

【ssl认证、证书】SSL 证书基本概念、证书格式、openssl和keytool的区别

文章目录1. keytool VS openssl2. X.509 VS PKCS2.1 PKCS2.2 X.5092.2.1 证书编码格式2.2.1.1 DER 证书编码格式二进制2.2.1.2 文本格式 pem2.2.2 文件后缀名3. 常见Web服务软件及证书格式参考相关文章&#xff1a;//-----------Java SSL begin----------------------【ssl认证…

【云原生】k8s集群命令行工具kubectl之集群管理命令

kubectl集群管理命令详解一、准备工作1.1、Replication Controller1.2、Deployment1.3、DaemonSet1.4、查看创建的svc和pod1.5、kubectl 命令自动补全设置二、集群管理命令2.1、top2.2、cordon2.3、uncordon2.4、drain2.5、taint2.5.1、污点设置。2.5.2、容忍度使用一、准备工作…

Scala之函数式编程

目录 函数和方法的区别&#xff1a; 参数默认值&#xff1a; 函数至简原则---能省则省&#xff1a; 至简原则细节 匿名函数的化简&#xff1a; 匿名函数至简原则&#xff1a; 高阶函数&#xff1a; 高阶函数的三种用法&#xff1a; &#xff08;1&#xff09;函数可以作…