头几天在CSDN上逛博客时遇到一篇非常有趣的博文,大意是将照片的内容用汉字来替换,看后觉得不错,决定分享给大家,下面就一起来看看吧。
一、实现原理
对于一幅图像而言,总是可转换成取值范围在[0, 255]之间灰度图像,将灰度图用最大灰度值作归一化处理,归一化后的值作为像素点所在位置的灰度密度;对于汉字而言,往往具有不同数量和形状的笔画,若在一个固定的区域内使用同一种字体书写汉字,则不同汉字所占的区域面积一般是不同的,将每个汉字所占区域面积与总区域面积作比,并把对应的比值作为汉字密度。若将图像灰度密度与汉字密度建立一一对应关系,即可把相同位置的像素点用对应像素密度的汉字来占据,这样就可以完成从像素图到字符化图的转换。
不难看出,算法主要包括两个部分:一是建立一个汉字密度库,包含汉字与其密度;二是实现汉字密度与图像灰度密度之间的转换。
二、实现过程
2.1 基于汉字库创建汉字密度库
% 字符转密度值
clc;clear;close all;
% 加载字库集,可以自由定义字库集
load('str.mat');
N = size(str,2);
% 初始化汉字密度矩阵
strR =zeros(N,1);
% 定义figur背景颜色
fig = figure('color',[1 1 1]);%白色背景
hold on;
% 限制X, Y坐标轴范围
xlim([0,0.5]);ylim([0,0.5]);
% 设置figure位置
set(gcf,'Position',[488 342 375 420]);
% 设置坐标轴位置
set(gca,'Position',[0.0 0.0 1 1]);
% 获取当前坐标轴句柄
ax = gca;
F = getframe;
strd = F.cdata;
% 计算整个坐标轴区域面积
aS = size(strd,1)*size(strd,2);
% 不显示坐标轴
axis off;
% 通过循环计算字库集中每个汉字对应的密度值
for k = 1:N
% 在figure指定位置放置文字
text(ax,0,0,str(k),'FontUnits','normalized','FontSize',0.9,'verticalAlignment','bottom');
% 获取文字图像信息
F = getframe;
strd = F.cdata;
% 计算文字所占密度
strdm = mean(strd,3);
strdm = uint8((strdm ~= 255));
% 计算汉字所占面积
aC = sum(strdm(:));
strR(k) = aC/aS;
% 清除当前坐标区域内汉字
cla;
end
% 保存每个字符密度
save('strR.mat','str','strR');
2.2 根据文字密度与图像灰度密度的对应关系,在相应位置进行汉字替换即可完成图像的字符化过程。
clc;clear;close;
% 加载字库集及其密度
load('strR.mat');
% 读取目标图片
x = imread('lenna.png');
% 重置图像尺寸
len = 80;
x = imresize(x,[len,len]);
% 将RGB图像转换为灰度图像
img = double(rgb2gray(x));
% 将灰度值用最大值归一化,越亮密度越低,越暗密度越高
img = 1 - img/255;
% 由于文字最大密度不能到1,而灰度密度可以取1,因此需要对文字的密度值进行缩放
enlarge = max(img(:))/max(strR(:));
% 初始化对应编码
strid = zeros(size(x(:,:,1)));
% 对每一个像素点的灰度值与文字密度进行匹配,记录下对应的文字编码
for k = 1:length(img(:))
imk = img(k);
[~,minid] = min(abs(imk-strR*enlarge));
strid(k) = minid;
end
% 按照行进行每行的文字输出
n = size(img,1);
strI = cell(1,n);
figure('color',[1 1 1])
for k=1:n
strI = str(strid(k,:));
%由于默认matlab中text的行间距太大,这里人为约束固定每一行位置
text(0,1-1/n*k,strI,'FontUnits','normalized','FontSize',1/n,...
'verticalAlignment','bottom','HorizontalAlignment','center');
end
%将文字居中
xlim([-1,1]);
axis off
F = getframe;
strdata=F.cdata;
% 保存图像
imwrite(strdata,'lennaNew.png');
处理前原始图
处理后效果图
肿么样?效果还不错吧!如果是视频,可以先对视频进行逐帧字符化处理,然后再逐帧整合就可以获得完整字符化效果的视频,这里就不给大家演示了,自行摸索吧。
参考资料:
原作者:hyhhyh21
原地址:https://blog.csdn.net/weixin_42943114/article/details/91406499
字库源:https://my.oschina.net/u/2510243/blog/716652/
图片来源:https://en.wikipedia.org/wiki/Lena_Forsén