菜单

H5游戏开发:消灭星星

2019年1月17日 - 金沙前端

3. Model

10 x 10 的表格用长度为 100 的数组可系数映射游戏的点滴「砖块」。

[ R, R, G, G, B, B, Y, Y, P, P, R, R, G, G, B, B, Y, Y, P, P, R, R, G,
G, B, B, Y, Y, P, P, R, R, G, G, B, B, Y, Y, P, P, R, R, G, G, B, B, Y,
Y, P, P, R, R, G, G, B, B, Y, Y, P, P, R, R, G, G, B, B, Y, Y, P, P, R,
R, G, G, B, B, Y, Y, P, P, R, R, G, G, B, B, Y, Y, P, P, R, R, G, G, B,
B, Y, Y, P, P ]

1
2
3
4
5
6
7
8
9
10
11
12
[
R, R, G, G, B, B, Y, Y, P, P,
R, R, G, G, B, B, Y, Y, P, P,
R, R, G, G, B, B, Y, Y, P, P,
R, R, G, G, B, B, Y, Y, P, P,
R, R, G, G, B, B, Y, Y, P, P,
R, R, G, G, B, B, Y, Y, P, P,
R, R, G, G, B, B, Y, Y, P, P,
R, R, G, G, B, B, Y, Y, P, P,
R, R, G, G, B, B, Y, Y, P, P,
R, R, G, G, B, B, Y, Y, P, P
]

R – 黑色,G – 黄色,B – 棕色,Y – 肉色,P – 藏肉色。Model
的中坚职责是以下四个:

一、画灰度图直方图

绘制都足以调用matplotlib.pyplot库来进展,其中的hist函数可以一贯绘制直方图。

调用方式:
n, bins, patches = plt.hist(arr, bins=50, normed=1, facecolor='green', alpha=0.75)
hist的参数非常多,但常用的就这五个,只有第一个是必须的,后面四个可选

arr: 需要计算直方图的一维数组

bins: 直方图的柱数,可选项,默认为10

normed: 是否将得到的直方图向量归一化。默认为0

facecolor: 直方图颜色

alpha: 透明度

返回值 :

n: 直方图向量,是否归一化由参数设定

bins: 返回各个bin的区间范围

patches: 返回每个bin里面包含的数据,是一个list

from PIL import Image
import numpy as np
import matplotlib.pyplot as plt
img=np.array(Image.open('len.jpg').convert('L'))

plt.figure("lena")
arr=img.flatten()
n, bins, patches = plt.hist(arr, bins=256, normed=1, facecolor='green', alpha=0.75)
print(n)
print(bins)
print(patches)
plt.show()

收获如下图所示:图片 1

一对开源图像处理库


GPUImage
是iOS下一个开源的基于GPU的图像处理库,提供各样各类的图像处理滤镜,并且协助照相机和视频机的实时滤镜。GPUImage
for
Android是它在Android下的贯彻,同样也是开源的。其中提供了几十多种常见的图形滤镜API,且其编制是依照GPU渲染,处理速度相应也正如快,是一个科学的图样实时处理框架。
GitHub地址:https://github.com/CyberAgent/android-gpuimage

援助一百多种图片处理功能

OpenCV是一个基于BSD许可(开源)发行的跨平台总计机视觉库,可以运行在Linux、Windows、Android和Mac
OS操作系统上。

参考资料:《Android群英传》

视频与图像RGB/YUV格式详解(转)
统计机彩色显示器呈现色彩的规律与多彩电视一样,都是行使R(Red)G(格林(Green))B(Blue)相加混色的原理:通过发射出两种不同强度的电子束,使屏幕内侧覆盖的红绿蓝磷光材料发光而发优良彩这种色彩的代表方法称为RGB色彩空间表示(它也是多媒体电脑技术中用得最多的一种色彩空间表示方法)
遵照三本色原理,任意一种色光F都得以用不同分量的RGB三色相加混合而成
F = r [ R ] + g [ G ] + b [ B ]
中间,rgb分别为三本色出席混合的周全当三本色分量都为0(最弱)时混合为绿色光;而当三本色分量都为k(最强)时混合为白色光调整rgb多个周详的值,可以勾兑出介于肉色光和白色光之间的应有尽有的色光
那就是说YUV又从何而来呢?在现代彩色电视机系统中,平时接纳三管彩色视频机或彩色CCD视频机举行拍摄,然后把摄得的彩色图像信号经分色分别放中将正后得到RGB,再经过矩阵变换电路得到亮度信号Y和六个色差信号R-Y(即U)B-Y(即V),最后发送端将亮度和色差两个信号分别展开编码,用同一信道发送出去这种色彩的意味方法就是所谓的YUV色彩空间表示
利用YUV色彩空间的要害是它的亮度信号Y和色度信号UV是分其余假诺只有Y信号分量而没有UV分量,那么这么表示的图像就是黑白灰度图像彩色电视机运用YUV空间正是为了用亮度信号Y解决彩色电视与黑白电视机的兼容问题,使黑白电视机也能接收彩色电视机信号
YUV与RGB互相转换的公式如下(RGB取值范围均为0-255):
Y = 0.299R + 0.587G + 0.114B
U = -0.147R – 0.289G + 0.436B
V = 0.615R – 0.515G – 0.100B
R = Y + 1.14V
G = Y – 0.39U – 0.58V
B = Y + 2.03U
在DirectShow中,常见的RGB格式有RGB1RGB4RGB8RGB565RGB555RGB24RGB32ARGB32等;常见的YUV格式有YUY2YUYVYVYUUYVYAYUVY41PY411Y211IF09IYUVYV12YVU9YUV411YUV420等作为视频媒体类型的佑助表达项目(Subtype),它们对应的GUID见表2.3
表2.3 常见的RGB和YUV格式
GUID 格式描述
MEDIASUBTYPE_RGB1 2色,每个像素用1位表示,需要调色板
MEDIASUBTYPE_RGB4 16色,每个像素用4位代表,需要调色板
MEDIASUBTYPE_RGB8 256色,每个像素用8位代表,需要调色板
MEDIASUBTYPE_RGB565 每个像素用16位表示,RGB分量分别使用5位6位5位
MEDIASUBTYPE_RGB555 每个像素用16位代表,RGB分量都选择5位(剩下的1位不用)
MEDIASUBTYPE_RGB24 每个像素用24位代表,RGB分量各使用8位
MEDIASUBTYPE_RGB32 每个像素用32位表示,RGB分量各使用8位(剩下的8位不要)
MEDIASUBTYPE_ARGB32 每个像素用32位表示,RGB分量各使用8位(剩下的8位用于表示Alpha通道值)
MEDIASUBTYPE_YUY2 YUY2格式,以4:2:2模式打包
MEDIASUBTYPE_YUYV YUYV格式(实际格式与YUY2相同)
MEDIASUBTYPE_YVYU YVYU格式,以4:2:2情势包装
MEDIASUBTYPE_UYVY UYVY格式,以4:2:2格局封装
MEDIASUBTYPE_AYUV 带Alpha通道的4:4:4 YUV格式
MEDIASUBTYPE_Y41P Y41P格式,以4:1:1格局包裹
MEDIASUBTYPE_Y411 Y411格式(实际格式与Y41P如出一辙)
MEDIASUBTYPE_Y211 Y211格式
MEDIASUBTYPE_IF09 IF09格式
MEDIASUBTYPE_IYUV IYUV格式
MEDIASUBTYPE_YV12 YV12格式
MEDIASUBTYPE_YVU9 YVU9格式
下面分别介绍各个RGB格式
¨ RGB1RGB4RGB8都是调色板类型的RGB格式,在叙述这些媒体类型的格式细节时,经常会在BITMAPINFOHEADER数据结构前边随着一个调色板(定义一层层颜色)它们的图像数据并不是实在的颜料值,而是当前像素颜色值在调色板中的索引以RGB1(2色位图)为例,比如它的调色板中定义的二种颜色值依次为0x000000(粉紫色)和0xFFFFFF(白色),那么图像数据001101010111(每个像素用1位表示)表示对应各像素的水彩为:黑黑白白黑白黑白黑白白白
¨ RGB565使用16位代表一个像素,这16位中的5位用于R,6位用于G,5位用于B程序中平常选取一个字(WORD,一个字十分多少个字节)来操作一个像素当读出一个像素后,这么些字的相继位意义如下:
高字节 低字节
R R R R R G G G G G G B B B B B
可以组合使用屏蔽字和移动操作来得到RGB各分量的值:
#define RGB565_MASK_RED 0xF800
#define RGB565_MASK_GREEN 0x07E0
#define RGB565_MASK_BLUE 0x001F
R = (wPixel & RGB565_MASK_RED) >> 11; // 取值范围0-31
G = (wPixel & RGB565_MASK_GREEN) >> 5; // 取值范围0-63
B = wPixel & RGB565_MASK_BLUE; // 取值范围0-31
¨ RGB555是另一种16位的RGB格式,RGB分量都用5位代表(剩下的1位不用)使用一个字读出一个像素后,这一个字的逐一位意义如下:
高字节 低字节
X R R R R G G G G G B B B B B (X表示不用,可以忽略)
可以组成使用屏蔽字和活动操作来拿到RGB各分量的值:
#define RGB555_MASK_RED 0x7C00
#define RGB555_MASK_GREEN 0x03E0
#define RGB555_MASK_BLUE 0x001F
R = (wPixel & RGB555_MASK_RED) >> 10; // 取值范围0-31
G = (wPixel & RGB555_MASK_GREEN) >> 5; // 取值范围0-31
B = wPixel & RGB555_MASK_BLUE; // 取值范围0-31
¨ RGB24使用24位来表示一个像素,RGB分量都用8位代表,取值范围为0-255专注在内存中RGB各分量的排列顺序为:BGR BGR BGR经常可以应用RGBTRIPLE数据结构来操作一个像素,它的定义为:
typedef struct tagRGBTRIPLE {
BYTE rgbtBlue; // 黄色分量
BYTE rgbt格林; // 青色分量
BYTE rgbtRed; // 黑色分量
} RGBTRIPLE;
¨ RGB32使用32位来代表一个像素,RGB分量各用去8位,剩下的8位用作Alpha通道或者不用(ARGB32就是带Alpha通道的RGB32)注目的在于内存中RGB各分量的排列顺序为:BGRA BGRA BGRA平常可以行使RGBQUAD数据结构来操作一个像素,它的定义为:
typedef struct tagRGBQUAD {
BYTE rgbBlue; // 紫色分量
BYTE rgb格林; // 粉红色分量
BYTE rgbRed; // 黑色分量
BYTE rgbReserved; // 保留字节(用作Alpha通道或疏忽)
} RGBQUAD;
下边介绍各样YUV格式YUV格式日常有两大类:打包(packed)格式和平面(planar)格式前者将YUV分量存放在同一个数组中,平常是多少个相邻的像素组成一个宏像素(macro-pixel);而后人使用五个数组分开存放YUV多少个轻重,就像是一个三维平面一样表2.3中的YUY2到Y211都是打包格式,而IF09到YVU9都是平面格式(注意:在介绍各种现实格式时,YUV各分量都会蕴藏下标,如Y0U0V0意味首个像素的YUV分量,Y1U1V1表示第二个像素的YUV分量,以此类推)
¨ YUY2(和YUYV)格式为各类像素保留Y分量,而UV分量在档次方向上每五个像素采样两次一个宏像素为4个字节,实际表示2个像素(4:2:2的趣味为一个宏像素中有4个Y分量2个U分量和2个V分量)图像数据中YUV分量排列顺序如下:
Y0 U0 Y1 V0 Y2 U2 Y3 V2
¨ YVYU格式跟YUY2类似,只是图像数据中YUV分量的排列顺序有所不同:
Y0 V0 Y1 U0 Y2 V2 Y3 U2
¨ UYVY格式跟YUY2类似,只是图像数据中YUV分量的排列顺序有所不同:
U0 Y0 V0 Y1 U2 Y2 V2 Y3
¨ AYUV格式带有一个Alpha通道,并且为每个像素都提取YUV分量,图像数据格式如下:
A0 Y0 U0 V0 A1 Y1 U1 V1
¨ Y41P(和Y411)格式为各类像素保留Y分量,而UV分量在档次方向上每4个像素采样一次一个宏像素为12个字节,实际表示8个像素图像数据中YUV分量排列顺序如下:
U0 Y0 V0 Y1 U4 Y2 V4 Y3 Y4 Y5 Y6 Y8
¨ Y211格式在档次方向上Y分量每2个像素采样两遍,而UV分量每4个像素采样五次一个宏像素为4个字节,实际表示4个像素图像数据中YUV分量排列顺序如下:
Y0 U0 Y2 V0 Y4 U4 Y6 V4
¨ YVU9格式为各种像素都提取Y分量,而在UV分量的提取时,首先将图像分成若干个4 x 4的宏块,然后每个宏块提取一个U分量和一个V分量图像数据存储时,首先是整幅图像的Y分量数组,然后就跟着U分量数组,以及V分量数组IF09格式与YVU9近乎
¨ IYUV格式为各种像素都提取Y分量,而在UV分量的领到时,首先将图像分成若干个2 x 2的宏块,然后每个宏块提取一个U分量和一个V分量YV12格式与IYUV类似
¨ YUV411YUV420格式多见于DV数据中,前者用于NTSC制,后者用于PAL制YUV411为各类像素都提取Y分量,而UV分量在档次方向上每4个像素采样两遍YUV420并非V分量采样为0,而是跟YUV411相对而言,在档次方向上增强一倍色差采样频率,在笔直方向上以U/V间隔的主意缩小一半色差采样,如下图所示

3.3 夯实砖墙

砖墙在解除了有些砖块后,会油可是生空洞,此时急需对墙体举办夯实:

向下夯实 向左夯实 向左下夯实(先下后左)

一种高效的实现方案是,每便「消除砖块」后一直遍历砖墙数组(10×10数组)再把空洞夯实,伪代码表示如下:

JavaScript

for(let row = 0; row < 10; ++row) { for(let col = 0; col < 10;
++col) { if(isEmpty(row, col)) { // 水平方向(向左)夯实
if(isEmptyCol(col)) { tampRow(col); } // 垂直方向(向下)夯实 else {
tampCol(col); } break; } } }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
for(let row = 0; row < 10; ++row) {
for(let col = 0; col < 10; ++col) {
if(isEmpty(row, col)) {
// 水平方向(向左)夯实
if(isEmptyCol(col)) {
tampRow(col);
}
// 垂直方向(向下)夯实
else {
tampCol(col);
}
break;
}
}
}

But…
为了夯实一个华而不实对一张大数组举行全量遍历并不是一种高效的算法。在笔者看来影响「墙体夯实」效率的元素有:

  1. 定点空洞
  2. 砖块移动(夯实)

环顾墙体数组的根本目标是「定位空洞」,可是否不扫描墙体数组直接「定位空洞」?

墙体的「空洞」是由于「消除砖块」造成的,换种说法 ——
被排除的砖块留下来的坑位就是墙体的悬空。在「消除砖块」的同时标记空洞的职位,这样就绝不全量扫描墙体数组,伪代码如下:

JavaScript

function deleteTile(tile) { // 标记空洞 markHollow(tile.index); //
删除砖块逻辑 … }

1
2
3
4
5
6
function deleteTile(tile) {
// 标记空洞
markHollow(tile.index);
// 删除砖块逻辑
}

在下面的夯实动图,其实可以看来它的夯实过程如下:

  1. 泛泛上方的砖块向下移动
  2. 空列左边的砖块向左移动

墙体在「夯实」过程中,它的境界是实时在扭转,假使「夯实」不按实际边界举办围观,会生出多余的空域扫描:

图片 2

怎样记录墙体的界限?
把墙体拆分成一个个独门的列,那么列最顶部的空白格片段就是墙体的「空白」,而任何非顶部的空白格片段即墙体的「空洞」。

图片 3

作者利用一组「列集合」来叙述墙体的境界并记录墙体的虚幻,它的模子如下:

JavaScript

/* @ count – 列砖块数 @ start – 顶部行索引 @ end – 底部行索引 @
pitCount – 坑数 @ topPit – 最顶部的坑 @ bottomPit – 最底部的坑 */ let
wall = [ {count, start, end, pitCount, topPit, bottomPit}, {count,
start, end, pitCount, topPit, bottomPit}, … ];

1
2
3
4
5
6
7
8
9
10
11
12
13
/*
@ count – 列砖块数
@ start – 顶部行索引
@ end – 底部行索引
@ pitCount – 坑数
@ topPit – 最顶部的坑
@ bottomPit – 最底部的坑
*/
let wall = [
{count, start, end, pitCount, topPit, bottomPit},
{count, start, end, pitCount, topPit, bottomPit},
];

本条模型可以描述墙体的多少个细节:

JavaScript

// 空列 if(count === 0) { ... } // 连续空洞 else if(bottomPit -
topPit + 1 === pitCount) { ... } // 非连续空洞 else { ... }

<table>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<tbody>
<tr class="odd">
<td><div class="crayon-nums-content" style="font-size: 13px !important; line-height: 15px !important;">
<div class="crayon-num" data-line="crayon-5b8f3d2c2df29914802382-1">
1
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f3d2c2df29914802382-2">
2
</div>
<div class="crayon-num" data-line="crayon-5b8f3d2c2df29914802382-3">
3
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f3d2c2df29914802382-4">
4
</div>
<div class="crayon-num" data-line="crayon-5b8f3d2c2df29914802382-5">
5
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f3d2c2df29914802382-6">
6
</div>
<div class="crayon-num" data-line="crayon-5b8f3d2c2df29914802382-7">
7
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f3d2c2df29914802382-8">
8
</div>
<div class="crayon-num" data-line="crayon-5b8f3d2c2df29914802382-9">
9
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f3d2c2df29914802382-10">
10
</div>
<div class="crayon-num" data-line="crayon-5b8f3d2c2df29914802382-11">
11
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f3d2c2df29914802382-12">
12
</div>
</div></td>
<td><div class="crayon-pre" style="font-size: 13px !important; line-height: 15px !important; -moz-tab-size:4; -o-tab-size:4; -webkit-tab-size:4; tab-size:4;">
<div id="crayon-5b8f3d2c2df29914802382-1" class="crayon-line">
// 空列
</div>
<div id="crayon-5b8f3d2c2df29914802382-2" class="crayon-line crayon-striped-line">
if(count === 0) { 
</div>
<div id="crayon-5b8f3d2c2df29914802382-3" class="crayon-line">
 ...
</div>
<div id="crayon-5b8f3d2c2df29914802382-4" class="crayon-line crayon-striped-line">
}
</div>
<div id="crayon-5b8f3d2c2df29914802382-5" class="crayon-line">
// 连续空洞
</div>
<div id="crayon-5b8f3d2c2df29914802382-6" class="crayon-line crayon-striped-line">
else if(bottomPit - topPit + 1 === pitCount) { 
</div>
<div id="crayon-5b8f3d2c2df29914802382-7" class="crayon-line">
 ...
</div>
<div id="crayon-5b8f3d2c2df29914802382-8" class="crayon-line crayon-striped-line">
}
</div>
<div id="crayon-5b8f3d2c2df29914802382-9" class="crayon-line">
// 非连续空洞
</div>
<div id="crayon-5b8f3d2c2df29914802382-10" class="crayon-line crayon-striped-line">
else {
</div>
<div id="crayon-5b8f3d2c2df29914802382-11" class="crayon-line">
 ...
</div>
<div id="crayon-5b8f3d2c2df29914802382-12" class="crayon-line crayon-striped-line">
}
</div>
</div></td>
</tr>
</tbody>
</table>

砖块在摒除后,映射到单个列上的空洞会有两种分布形态 —— 连续与非连续。

图片 4

「连续空洞」与「非连续空洞」的夯实过程如下:

图片 5

其实「空列」放大于墙体上,也会有「空洞」类似的遍布形态 ——
连续与非连续。
图片 6

它的夯实过程与虚空类似,这里就不赘述了。

  1. 首先安装pytyhon,linux系统中
    已经协调带了python,至于在window系统只设置则更为简约,下载一个Anaconda直接就可以安装了,后续的模块安装则一向利用pip安装会更加便利。在此处就不一一讲述了。
改变色光属性

系统封装了一个类—ColorMatrix,通过这个类,可以很有益地经过转移矩阵值来处理颜色效果(色调、饱和度、亮度)。本质上是一个一维数组[a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t]。

图片 7

ColorMatrix

调剂色调(色彩的团团转运算):
  ColorMatrix类提供了setRotate(int axis, float
degrees)来调节颜色的色泽。第一个参数,使用0、1、2来代表Red、格林(Green)、Blue两种颜色的拍卖,第二个参数,就是内需处理的值。

    /**
     * Set the rotation on a color axis by the specified values.
     * <p>
     * <code>axis=0</code> correspond to a rotation around the RED color
     * <code>axis=1</code> correspond to a rotation around the GREEN color
     * <code>axis=2</code> correspond to a rotation around the BLUE color
     * </p>
     */
    public void setRotate(int axis, float degrees) {
        reset();
        double radians = degrees * Math.PI / 180d;
        float cosine = (float) Math.cos(radians);
        float sine = (float) Math.sin(radians);
        switch (axis) {
        // Rotation around the red color
        case 0:
            mArray[6] = mArray[12] = cosine;
            mArray[7] = sine;
            mArray[11] = -sine;
            break;
        // Rotation around the green color
        case 1:
            mArray[0] = mArray[12] = cosine;
            mArray[2] = -sine;
            mArray[10] = sine;
            break;
        // Rotation around the blue color
        case 2:
            mArray[0] = mArray[6] = cosine;
            mArray[1] = sine;
            mArray[5] = -sine;
            break;
        default:
            throw new RuntimeException();
        }
    }

调节饱和度
  通过色彩的移位运算单独增强R,G,B的饱和度,ColorMatrix类提供了setSaturation(float
sat)方法来完全调节图像的饱和度,参数代表设置颜色饱和度的值,当饱和度为0时,图像成为灰度图像,数值越大图像越饱和。

    /**
     * Set the matrix to affect the saturation of colors.
     *
     * @param sat A value of 0 maps the color to gray-scale. 1 is identity.
     */
    public void setSaturation(float sat) {
        reset();
        float[] m = mArray;

        final float invSat = 1 - sat;
        final float R = 0.213f * invSat;
        final float G = 0.715f * invSat;
        final float B = 0.072f * invSat;

        m[0] = R + sat; m[1] = G;       m[2] = B;
        m[5] = R;       m[6] = G + sat; m[7] = B;
        m[10] = R;      m[11] = G;      m[12] = B + sat;
    }

调剂亮度(色彩的缩放运算)
  当三原色以平等的百分比举办混合的时候,就会显得出白色,使用那个规律来改变一个图像的亮度,亮度为0时,图像成为全黑。ColorMatrix类提供setScale(float
rScale, float gScale, float bScale, float
aScale)方法来调节颜色的亮度值。

    /**
     * Set this colormatrix to scale by the specified values.
     */
    public void setScale(float rScale, float gScale, float bScale,
                         float aScale) {
        final float[] a = mArray;

        for (int i = 19; i > 0; --i) {
            a[i] = 0;
        }
        a[0] = rScale;
        a[6] = gScale;
        a[12] = bScale;
        a[18] = aScale;
    }

1. 游戏规则

「消灭星星」存在三个版本,不过它们的平整除了「关卡分值」有些出入外,此外的条条框框都是一模一样的。笔者介绍的本子的游戏规则整理如下:

1. 色砖遍布

2. 拔除规则

五个或两个以上同色砖块相连通即是可被排除的砖头。

3. 分值规则

「n」表示砖块数量。下边是「总」分值的平整,还有「单」个砖块的分值规则:

「i」表示砖块的索引值(从 0
开首)。简单地说,单个砖块「得分值」和「扣分值」是一个等差数列。

4. 关卡分值

关卡分值 = 1000 + (level – 1) * 2000;「level」即当前关卡数。

5. 合格条件

下面五个原则还要建立游戏才方可过得去。

图像保存

img.save('d:/lena.jpg')

注:前边的转向代码处理情势不平等,另外都是平等的,所以并未写代码

局部常用的图像颜色处理矩阵

图片 8

灰度矩阵

图片 9

灰度效果

图片 10

图像反转矩阵

图片 11

图像反转效果

图片 12

怀旧矩阵

图片 13

忆旧效果

图片 14

去色矩阵

图片 15

去色效果

3.1 生成砖墙

砖墙分两步生成:

反驳上,可以将 100 个格子可以均分到 5
类颜色,可是笔者玩过的「消灭星星」都不利用均分政策。通过分析几款「消灭星星」,其实可以发现一个法则
—— 「色砖之间的数码差在一个恒定的间隔内」。

只要把传统意义上的均分称作「完全均分」,那么「消灭星星」的分红是一种在均分线上下波动的「不完全均分」。

图片 16

笔者把下面的「不完全均分」称作「波动均分」,算法的求实实现可以瞻仰「兵荒马乱均分算法」。

「打散色砖」其实就是将数组乱序的历程,笔者推荐应用「
费雪耶兹乱序算法」。

以下是伪代码的实现:

JavaScript

// 波动均分色砖 waveaverage(5, 4, 4).forEach( // tiles 即色墙数组
(count, clr) => tiles.concat(generateTiles(count, clr)); ); //
打散色砖 shuffle(tiles);

1
2
3
4
5
6
7
// 波动均分色砖
waveaverage(5, 4, 4).forEach(
// tiles 即色墙数组
(count, clr) => tiles.concat(generateTiles(count, clr));
);
// 打散色砖
shuffle(tiles);

图像类型转化convert函数

python图像处理库PIL对于PNG、BMP和JPG彩色图像格式之间的互动转换都得以经过Image模块的open()和save()函数来完成。具体说就是,在开辟这一个图像时,PIL会将它们解码为三通道的“RGB”图像。用户可以依照那一个“RGB”图像,对其开展拍卖。处理完毕,使用函数save(),可以将处理结果保存成PNG、BMP和JPG中另外格式。这样也就完成了三种格式之间的变换。同理,其他格式的彩色图像也能够透过这种艺术成就更换。当然,对于不同格式的灰度图像,也可由此类似途径完成,只是PIL解码后是情势为“L”的图像。我们以图像图片 17为例,分辨率为512×512。

  1. 格局“RGB”转换为其余不同情势

a. 形式“1”
情势“1”为二值图像,非黑即白。但是它每个像素用8个bit表示,0象征黑,255象征白。下边我们将lena图像转换为“1”图像。

lena_1 = lena.convert("1")
print(lena_1.mode)
lena_1.show()

b. 模式“L”
形式“L”为棕色图像,它的每个像素用8个bit表示,0意味黑,255意味白,其他数字代表不同的灰度。在PIL中,从情势“RGB”转换为“L”格局是按部就班下边的公式转换的:
L = R * 299/1000 + G * 587/1000+ B * 114/1000
下面我们将lena图像转换为“L”图像。

lena_1 = lena.convert("L")
print(lena_1.mode)
lena_1.show()

c模式“P”
形式“P”为8位彩色图像,它的各种像素用8个bit表示,其相应的彩色值是遵照调色板查询出来的。上面我们利用默认的调色板将lena图像转换为“P”图像。

lena_1 = lena.convert("P")
print(lena_1.mode)
lena_1.show()

d 格局“RGBA”
格局“RGBA”为32位彩色图像,它的各种像素用32个bit表示,其中24bit象征藏青色、黄色和灰色五个通道,另外8bit表示alpha通道,即透明通道。

lena_1 = lena.convert("RGBA")
print(lena_1.mode)
lena_1.show()

e 格局“CMYK”
形式“CMYK”为32位彩色图像,它的各类像素用32个bit表示。格局“CMYK”就是印刷四分色情势,它是色彩缤纷印刷时采用的一种套色形式,利用色料的三原色混色原理,加上肉色油墨,共计四种颜色混合叠加,形成所谓“全彩印刷”。
四种标准颜色是:C:Cyan = 褐色,又叫做‘天黄色’或是‘湛蓝’M:Magenta =
品红色,又称为‘洋肉色’;Y:Yellow = 粉红色;K:Key Plate(blacK) =
定位套版色(灰色)。

从实例中得以查出PIL中“RGB”转换为“CMYK”的公式如下: C = 255 – R M = 255 –
G Y = 255 – B K = 0 由于该转换公式相比简单,转换后的图像颜色稍微失真。

f 格局“YCbCr”
情势“YCbCr”为24位彩色图像,它的每个像素用24个bit表示。YCbCr其中Y是指亮度分量,Cb指紫色色度分量,而Cr指黄色色度分量。人的双眼对视频的Y分量更灵敏,因而在经过对色度分量举办子采样来压缩色度分量后,肉眼将发现不到的图像质料的扭转。
情势“RGB”转换为“YCbCr”的公式如下: Y= 0.257R+0.504G+0.098B+16 Cb =
-0.148
R-0.291G+0.439B+128 Cr = 0.439R-0.368G-0.071*B+128

依据公式,Y = 0.257197+0.564111+0.09878+16= 136.877 Cb=
-0.148
197-0.291111+0.43978+128= 100.785 Cr =
0.439197-0.368111-0.071*78+128 = 168.097
不问可知,PIL中不要按照这多少个公式举办“RGB”到“YCbCr”的转移。

g 模式“I”
情势“I”为32位整型褐色图像,它的每个像素用32个bit表示,0象征黑,255代表白,(0,255)之间的数字代表不同的灰度。在PIL中,从格局“RGB”转换为“I”形式是遵循上面的公式转换的:
I = R * 299/1000 + G * 587/1000 + B * 114/1000

h 情势“F”
情势“F”为32位浮点黄色图像,它的每个像素用32个bit表示,0意味着黑,255意味着白,(0,255)之间的数字代表不同的灰度。在PIL中,从格局“RGB”转换为“F”情势是坚守下边的公式转换的:
F = R * 299/1000+ G * 587/1000 + B * 114/1000

图像的变形处理平常包含以下基本转移

图片 18

平移变换

矩阵变换:

图片 19

平移变换矩阵

图片 20

旋转变换

能够赢得:

x0 = r*cosα 
y0 = r*sinα 
x = r*cos(α+θ) = r*cosα*cosθ − r*sinα*sinθ = x0*cosθ − y0*sinθ 
y = r*sin(α+θ) = r*sinα*cosθ + r*cosα*sinθ = y0*cosθ + x0*sinθ

矩阵变换如下:

图片 21

旋转矩阵变换

如上是以坐标原点为旋转主旨开展旋转变换,假诺以任意点O为旋转中央来开展旋转变换,平日需要以下五个步骤:
  1、将坐标原点平移到O点
  2、使用前边讲的以坐标原点为基本的团团转模式举办旋转变换
  3、将坐标原点还原

图片 22

缩放矩阵变换

图片 23

水平错切

图片 24

水平错切矩阵变换

垂直错切:
  x1 = x0
  y1 = K2 * x0 + y0

图片 25

笔直错切

图片 26

垂直错切矩阵变换

相关文章

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图