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

压缩包

相关推荐
Not Dr.Wang4222 分钟前
FIR数字滤波器设计的两种实现
matlab
3GPP仿真实验室3 分钟前
【MATLAB源码】CORDIC-QR :基于Cordic硬件级矩阵QR分解
开发语言·matlab·矩阵
民乐团扒谱机10 小时前
【微实验】机器学习之集成学习 GBDT和XGBoost 附 matlab仿真代码 复制即可运行
人工智能·机器学习·matlab·集成学习·xgboost·gbdt·梯度提升树
Evand J10 小时前
TDOA(到达时间差)的GDOP和CRLB计算的MATLAB例程,论文复现,附参考文献。GDOP:几何精度因子&CRLB:克拉美罗下界
开发语言·matlab·tdoa·crlb·gdop
机器学习之心HML13 小时前
MATLAB豆渣发酵工艺优化 - 基于响应面法结合遗传算法
matlab
aini_lovee1 天前
MATLAB基于小波技术的图像融合实现
开发语言·人工智能·matlab
3GPP仿真实验室1 天前
【Matlab源码】6G候选波形:OFDM-IM 增强仿真平台 DM、CI
开发语言·matlab·ci/cd
rit84324992 天前
MATLAB中Teager能量算子提取与解调信号的实现
开发语言·matlab
我找到地球的支点啦2 天前
通信扩展——扩频技术(超级详细,附带Matlab代码)
开发语言·matlab
Dev7z2 天前
基于 MATLAB 的铣削切削力建模与仿真
开发语言·matlab