先看一张正常的图像,图像尺寸为640x558

人脸部分打赏马赛克,效果如下:


可以看出,马赛克为一个个的晶体小方格,每个小方格的各个像素颜色是一样的。

现在简单说明下,马赛克的原理。
我们列举一些数字,共5行8列,40个数字。
1 2 3 4 5 6 7 8
9 10 11 12 13 14 15 16
17 18 19 20 21 22 23 24
25 26 27 28 29 30 31 32
33 34 35 36 37 38 39 40

我们不妨将这40个数字看成40个像素,马赛克就是将这些像素相邻的像素进行归一化,取这些相邻数字的平均数,然后用这个平均数替代原来的数。

比如相邻定义为2x2,即相邻的4个进行归一化,则1,2,9,10为一组;3,4,11,12为一组;17,18,25,26为一组,33,34为一组。
其中第一组1,2,9,10的和为22,取平均数5(22/4),然后将这四个数字都替换成5;经过这样的处理后,
原来的数字变成如下模式:
5 7 9 11
21 23 25 27
33 35 37 39

打马赛克就是选定区域,然后将这块区域划分若干个晶体小方格,每个晶体小方格里面的rgb三原色取平均值。

本文采取开源库cximage进行图片像素的处理。
代码不多,直接粘贴出来,其中iGridLength为晶体小方格的尺寸,iGridLength为2时,表示2x2,为4表示4x4。
注意:cximage读取jpg像素时,像素数据顺序都是从最后一行到第一行,从左到右。

// CxImageTest.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//#include <iostream>
#include <Windows.h>#include "cximage/ximage.h"std::wstring string2wstring(const std::string& str)
{std::wstring result;//获取缓冲区大小,并申请空间,缓冲区大小按字符计算  int len = MultiByteToWideChar(CP_ACP, 0, str.c_str(), str.size(), NULL, 0);TCHAR* buffer = new TCHAR[len + 1];//多字节编码转换成宽字节编码  MultiByteToWideChar(CP_ACP, 0, str.c_str(), str.size(), buffer, len);buffer[len] = '\0';             //添加字符串结尾  //删除缓冲区并返回值  result.append(buffer);delete[] buffer;return result;
}int main()
{CxImage image(CXIMAGE_FORMAT_JPG);image.Load(L"E:\\learn\\c++\\cximage\\CxImageTest\\x64\\Release\\qiushuzhen_640x558.jpeg", CXIMAGE_FORMAT_JPG);int iJpgWidth = image.GetWidth();int iJpgHeight = image.GetHeight();long x1 = 0;long y1 = 0;image.GetOffset(&x1, &y1);const int iBeginX = 256;const int iBeginY = 96;const int iEndX = 424;const int iEndY = 280;int iRSum = 0;int iGSum = 0;int iBSum = 0;int iAverageR = 0;int iAverageG = 0;int iAverageB = 0;int iGridLength = 2;for (int x = iBeginX; x < iEndX; x = x + iGridLength){for (int y = iBeginY; y < iEndY; y = y + iGridLength){int iPartGridXNum = 0;int iPartGridYNum = 0;for (int iSpanX = 0; iSpanX < iGridLength; iSpanX++){if (x + iSpanX < iEndX){iPartGridXNum++;}}for (int iSpanY = 0; iSpanY < iGridLength; iSpanY++){if (y + iSpanY < iEndY){iPartGridYNum++;}}iRSum = 0;iGSum = 0;iBSum = 0;int iPartGridNum = iPartGridXNum * iPartGridYNum;for (int i = x; i < x + iPartGridXNum; i++){for (int j = y; j < y + iPartGridYNum; j++){RGBQUAD rgb = image.GetPixelColor(i, (iJpgHeight - 1) - j, false);iRSum += rgb.rgbRed;iGSum += rgb.rgbGreen;iBSum += rgb.rgbBlue;}}iAverageR = iRSum / iPartGridNum;iAverageG = iGSum / iPartGridNum;iAverageB = iBSum / iPartGridNum;COLORREF color = COLORREF(RGB(iAverageR, iAverageG, iAverageB));for (int i = x; i < x + iPartGridXNum; i++){for (int j = y; j < y + iPartGridYNum; j++){image.SetPixelColor(i, (iJpgHeight - 1) - j, color);}}}}std::string strSavePath = "E:\\learn\\c++\\cximage\\CxImageTest\\x64\\Release\\";char szPicName[100] = { 0 };sprintf(szPicName, "qiushuzhen_640x558_msk_%dx%d.jpeg", iGridLength, iGridLength);strSavePath = strSavePath + szPicName;std::wstring strwSavePath = string2wstring(strSavePath);image.Save(strwSavePath.c_str(), CXIMAGE_FORMAT_JPG);return 0;
}

本人尝试了2x2,4x4,8x8,16x16,32x32五种晶体小方格进行打马赛克,其中32x32就是本文前面部分的马赛克尺寸。
2x2的效果如下:

可以看出2x2情况下,完全看不出打了马赛克。

4x4的效果如下:

可以看出4x4已经有点马赛克效果了

8x8的效果如下:

马赛克效果很明显了

16x16的效果如下:

这时已经分辨不出是谁了。

本人就代码例子进行了百度网盘共享:
链接:https://pan.baidu.com/s/1nPO-XRcEVtD_mjuE9K2OKw
提取码:1234

一个简单的马赛克例子相关推荐

  1. mvc登录实例 mysql_spring mvc + mybatis + mysql 调整的一个简单的登录例子

    spring mvc + mybatis + mysql 整合的一个简单的登录例子 今天用spring跟mybatis整合写了一个简单的登录例子,第一次整合,给自己做个笔记,可能注释写的有点少,做的不 ...

  2. boost::log模块实现一个简单日志的例子

    boost::log模块实现一个简单日志的例子 实现功能 C++实现代码 实现功能 boost::log模块实现一个简单日志的例子 C++实现代码 #include <boost/log/tri ...

  3. 轻松创建nodejs服务器(1):一个简单nodejs服务器例子

    这篇文章主要介绍了一个简单nodejs服务器例子,本文实现了一个简单的hello world例子,并展示如何运行这个服务器,需要的朋友可以参考下 我们先来实现一个简单的例子,hello world. ...

  4. 一个简单的CORBA例子

    因为对CORBA分析的需要,这里写一个简单的CORBA例子.从JDK1.2开始,JDK中集成了ORB的实现,本例子使用了JDK1.7,对于JDK1.2+应该都没有问题.这个例子实现一个简单的加减乘除的 ...

  5. 使用Multiplayer Networking做一个简单的多人游戏例子-1/3(Unity3D开发之二十五)

    猴子原创,欢迎转载.转载请注明: 转载自Cocos2Der-CSDN,谢谢! 原文地址: http://blog.csdn.net/cocos2der/article/details/51006463 ...

  6. java servlet例子_Servlet学习教程(三)---- 一个简单的Servlet例子

    我们用个最简单的Servlet例子来解说一下Servlet简单配置以及Servlet类实现类的写法. 第一,我们新建一个Dynamic Web Project,起名Servlet 点击NEXT,设置D ...

  7. Python网络爬虫 - 一个简单的爬虫例子

    下面我们创建一个真正的爬虫例子 爬取我的博客园个人主页首页的推荐文章列表和地址 scrape_home_articles.py from urllib.request import urlopen f ...

  8. python网页爬虫例子_Python网络爬虫 - 一个简单的爬虫例子

    下面我们创建一个真正的爬虫例子 爬取我的博客园个人主页首页的推荐文章列表和地址 scrape_home_articles.py from urllib.request importurlopenfro ...

  9. 决策树分析例题经典案例_决策树原理及一个简单的小例子

    首先通过两个图来引入什么是决策树. 是否学习的决策过程 决策树是仿树结构来进行决策的,例如上图来说,我们要对'是否学习'这个问题进行决策时,通常伴随一系列的子决策.先看是否有'对象',有的话是否需要' ...

最新文章

  1. 2022秋招算法岗卷成人间地狱!高薪惹眼,招录比100:1
  2. NYOJ 353 3D dungeon 【bfs】
  3. oracle创建数据库的三种方法
  4. CodeForces - 444C DZY Loves Colors(线段树+剪枝)
  5. 从头学习MVC4基础之视图
  6. windows phone笔记
  7. vulkan android 三星,vulkan android
  8. 数组作为方法的参数实例和细节(Java)
  9. Python2.7安装Numpy
  10. iTOP4412 uboot移植教程
  11. Android Studio Entry name *.xml collided解决方案
  12. laravel框架使用教程
  13. From.List用法详解
  14. 字节跳动做教育能否摆脱互联网公司“流量魔咒”?
  15. IEMS_11_课程信息相关的初始数据导入
  16. 摄影后期人像高端摄影后期PS修图技巧
  17. C# WAV音乐多音轨合并
  18. 在Qt中使用OpenGL(四)
  19. 机器学习—特征工程—OneHotEncoder独热编码
  20. 面试被骗 :当了一小时讲师,最后反倒说我不合格

热门文章

  1. Linux下如何拷贝隐藏文件
  2. 盘点个人信息保护方面的那些认证
  3. 深入探索C++对象模型之C++对象(vs,gcc,clang测试)
  4. 自定义ironic-python-agent镜像 ipa ramdisk and kernel
  5. 有时候人们用四位数字表示一个时间,比如 1106 表示 11 点零 6 分。现在,你的程序要根据起始时间和流逝的时间计算出终止时间。 读入两个数字,第一个数字以这样的四位数字表示当前时间,第二个数字
  6. Cuba 获取当前登录用户
  7. windows10应用商店打不开
  8. 帝国cms插件支持7.0/7.2 7.5/UTF-8 微信登入插件 一键登入
  9. dmpython部署操作轨迹
  10. 出走的门徒之七—驭势 吴甘沙:一步十年