MATLAB | 如何使用MATLAB一键生成拼豆图纸

最近迷上玩拼豆,就想着能不能写个MATLAB版本的拼豆图纸生成器,目前还是一个很简易版本,只支持生成方形图纸,且不太适合生成超大图(色号显示不清晰),大家可以自行添加功能,或做成App designer 形式。

注意这里如果图像四周如果不是透明的,那么白色像素也会被计数,因此底下显示H1色号会需要非常多,因此代码还有改进的空间,之后可以通过检测白色的连通区域,然后看看是否被其他颜色完全包围来决定是否被统计。。。此外之后可能会尝试对轮廓线条进行自动加粗后再生成图纸。。


1 属性设置

代码就直接点击运行,然后选择想要生成图纸的图片即可,图片如果是非正方形会被自动切割。

代码的最前面几行是:

matlab 复制代码
% 像素画大小; 最大颜色数量
pixN = 50; maxC = 60;
% 是否显示色号, 字体大小
showCName = true; fontSZ = 7;
% 读取色卡
% CData = load('mard188.mat');
CData = load('mard221.mat');
% 色号位置 'bottom'/'right'
palettePos = 'right';

是否显示色号

showCName可以被设置为 true/false,分别有以下效果:

画布尺寸和颜色数量

maxC为最大颜色数量,以下是分别设置为32和8的效果:


pixN是画布尺寸,不建议设置50以上,以下为设置为30的效果:

色卡

色卡这里给了一个188色的mard色卡和一个221色mard色卡,想要用其他牌子的拼豆可以自己制作一个mat文件。

色号位置

可以选择显示在下方还是右侧:


2 其他效果图展示

由于没写轮廓加粗的代码,所以本代码比较适合边缘没那么清晰的图像,此外mard牌子蓝紫色种类比较少,蓝紫色图像绘制效果会稍微差一些:

也可以制作一些游戏角色的拼豆图纸:


3 完整代码

完整代码无配色包文件无法运行,建议从文末链接直接下载包含配色包的压缩包,这里给出代码纯属凑字数。

matlab 复制代码
% 像素画大小; 最大颜色数量
pixN = 50; maxC = 60;
% 是否显示色号, 字体大小
showCName = true; fontSZ = 7;
% 读取色卡
% CData = load('mard188.mat');
CData = load('mard221.mat');
% 色号位置 'bottom'/'right'
palettePos = 'right';


% 读取图片并预处理
[filename, filepath] = uigetfile({'*.jpg;*.png;*.bmp;*.tiff', 'Image Files'}, 'Select an Image');
[img, ~, alp] = imread(fullfile(filepath, filename));
[M, N, ~] = size(img); img = double(img)./255; alp = double(alp)./255;
szN = min(M, N) - mod(min(M, N), pixN);
img = img((1:szN) + round((M - szN)/2), (1:szN) + round((N - szN)/2), :);
szB = round([szN, szN]/pixN); 
imgBR = blockproc(img(:,:,1), szB, @(block) mean(block.data(:)));
imgBG = blockproc(img(:,:,2), szB, @(block) mean(block.data(:)));
imgBB = blockproc(img(:,:,3), szB, @(block) mean(block.data(:)));

if ~isempty(alp)
    alp = alp((1:szN) + round((M - szN)/2), (1:szN) + round((N - szN)/2), :);
    alpB = blockproc(alp, szB, @(block) mean(block.data(:)));
    imgBR(alpB < .5) = 1; imgBG(alpB < .5) = 1; imgBB(alpB < .5) = 1;
end

% 颜色识别 
% 首先识别每个像素最接近哪种颜色,统计各种颜色出现次数
% 之后舍去出现次数少的颜色重新再识别一次
RGB = CData.rgb; CN = size(RGB, 1);
dis = + (repmat(imgBR(:), [1, CN]) - repmat(RGB(:,1).', [pixN^2, 1])).^2 ...
      + (repmat(imgBG(:), [1, CN]) - repmat(RGB(:,2).', [pixN^2, 1])).^2 ...
      + (repmat(imgBB(:), [1, CN]) - repmat(RGB(:,3).', [pixN^2, 1])).^2;
[~, indC] = min(dis, [], 2);
countC = sum(repmat(indC, [1, CN]) == repmat(1:CN, [pixN^2, 1]), 1);
[countNC, indNC] = sort(countC, 'descend');
indNC = sort(indNC(1:min(find(countNC > 0, 1, 'last'), maxC)));
CName = CData.palette(indNC, 1); RGB = CData.rgb(indNC, :); CN = length(indNC);

dis = + (repmat(imgBR(:), [1, CN]) - repmat(RGB(:,1).', [pixN^2, 1])).^2 ...
      + (repmat(imgBG(:), [1, CN]) - repmat(RGB(:,2).', [pixN^2, 1])).^2 ...
      + (repmat(imgBB(:), [1, CN]) - repmat(RGB(:,3).', [pixN^2, 1])).^2;
[~, indC] = min(dis, [], 2);
countC = sum(repmat(indC, [1, CN]) == repmat(1:CN, [pixN^2, 1]), 1);

% 创建图窗
fig = figure('WindowState', 'maximized');
ax = axes('Parent',fig, 'DataAspectRatio',[1,1,1], 'NextPlot','add', ...
    'Position',[0,0,1,1], 'XColor','none', 'YColor','none');

% 绘制像素
for i = 1:length(indNC)
    if all(RGB(i, :) == 1)
    else
        tind = find(indC == i);
        [ti, tj] = ind2sub([pixN, pixN], tind);
        ii = repmat(ti, [1, 4]); jj = repmat(tj, [1, 4]); 
        xx = jj - repmat([0,1,1,0], [size(jj,1), 1]);
        yy = pixN + 1 - ii - repmat([0,0,1,1], [size(ii,1), 1]);
        fill(xx.', yy.', RGB(i,:))
        textC = (mean(RGB(i,:)) < .5).*[1,1,1];
        if showCName
        text(tj - .5, pixN + .5 - ti, CName{i}, 'FontSize',fontSZ, 'Color',textC, ...
            'FontName','Times New Roman', 'HorizontalAlignment','center')
        end
    end
end
fill([-1,pixN,pixN,-1], [-1,-1,0,0], [17,112,189]./255, 'EdgeColor','none')
fill([-1,-1,0,0], [-1,pixN,pixN,-1], [17,112,189]./255, 'EdgeColor','none')
for i = 1:pixN
    text([-.5; i - .5], [i - .5; -.5], num2str(i), 'FontSize',fontSZ+1, 'Color','w', ...
        'FontName','Times New Roman', 'HorizontalAlignment','center')
end

% 绘制网格线
xx = [-1:pixN; -1:pixN; nan(1, pixN + 2)]; 
yy = [zeros(1, pixN + 1) - 1; ones(2, pixN + 1).*pixN];
plot([xx(:); yy(:)], [yy(:); xx(:)], 'LineWidth',.5, 'Color',[0,0,0])
xx = [-1, 0:5:pixN; -1, 0:5:pixN; nan(1,length(0:5:pixN)+1)]; 
yy = [zeros(1,length(0:5:pixN)+1) - 1; ones(2,length(0:5:pixN)+1).*pixN];
plot([xx(:); yy(:)], [yy(:); xx(:)], 'LineWidth',1, 'Color',[0,0,0])

if strcmp(palettePos, 'bottom')
    colN = floor((pixN + 1.5)/(3.5));
    for i = 1:length(indNC)
        fill([-1,2,2,-1] + mod(i - 1, colN)*3.5, [-1.5,-1.5,-2.5,-2.5] - floor((i-1)/colN)*1.5, RGB(i,:))
        textC = (mean(RGB(i,:)) < .5).*[1,1,1];
        text(mod(i - 1, colN)*3.5 + .5, - 2 - floor((i-1)/colN)*1.5, [CName{i}, ' (',num2str(countC(i)),')'], ...
            'FontSize',fontSZ+1, 'Color',textC, ...
            'FontName','Times New Roman', 'HorizontalAlignment','center')
    end
else
    rowN = floor((pixN + 1.5)/(1.5)); 
    for i = 1:length(indNC)
        fill([0,3,3,0] + pixN + .5 + floor((i-1)/rowN)*3.5, pixN + [0,0,-1,-1] - mod(i - 1, rowN)*1.5, RGB(i,:))
        textC = (mean(RGB(i,:)) < .5).*[1,1,1];
        text(pixN + 2 + floor((i-1)/rowN)*3.5, pixN -.5 - mod(i - 1, rowN)*1.5, [CName{i}, ' (',num2str(countC(i)),')'], ...
            'FontSize',fontSZ+1, 'Color',textC, ...
            'FontName','Times New Roman', 'HorizontalAlignment','center')
    end
end

axis tight

压缩包

相关推荐
ytttr8732 小时前
MATLAB基于LDA的人脸识别算法实现(ORL数据库)
数据库·算法·matlab
wuk9982 小时前
matlab为地图进行四色着色
开发语言·matlab
元周民4 小时前
matlab求两个具有共根的多项式的所有共根(未详细验证)
开发语言·matlab
代码小小只6 小时前
考虑不确定性的电动汽车优化问题
matlab
yong99908 小时前
基于小波分析与粒子群算法的电网潮流优化实现(MATLAB)
开发语言·算法·matlab
Dev7z9 小时前
基于MATLAB HSI颜色空间的图像美颜系统设计与实现
开发语言·matlab
ghie909010 小时前
MATLAB 高速公路裂缝检测
开发语言·matlab
天呐草莓12 小时前
热传导方程
算法·matlab
hoiii18713 小时前
基于MATLAB实现无监督数据建模
开发语言·matlab
kaikaile199515 小时前
使用纯MATLAB M函数实现的无刷直流电机控制系统仿真
开发语言·matlab