Article Summary
GPT 4

pillow

图片通常使用pillow库进行操作。

常用模块

Image
from PIL import Image
pic = Image.new(RGB,(width, height), (255, 255, 255)) #新建一个图片文件
#不写颜色数据则默认为(0, 0, 0)

pic = Image.open(data.png) #打开一个图片文件
pic = Image.open(data.png).convert(L) #以灰度模式打开一个图片文件

width, height = pic.size #获取图片的宽高
pic.putpixel((x,y),(100, 100, 100)) #对(x,y)坐标的像素点填充颜色,左上角坐标为(0, 0)

pic.show() #用默认图片软件展示图片
pic.save() #保存图片,可写路径,默认与python文件同路径

提取一部分

pic_1=pic.crop(x1,x2,y1,y2)#前面为左上坐标,后边为右下角坐标
#一张照片分为多块保存。
a=30
b=45
for x in range(80):
    for y in range(80):
        box=(x*a,y*b,(x+1)*a,(y+1)*b)
        f=image.crop(box)#每块碎片为30*45
        f.save()
ImageDraw
from PIL import ImageDraw
pic = Image.new(RGB,(width, height),(0,0,0))
draw = ImageDraw.ImageDraw(pic)  #创建绘画对象

参数:

fill = fillColor ,填充颜色
outline = outlineColor , 边框颜色

draw.rectangle((x1,y1,x2,y2),fill = (255,255,255),outline = (0,0,0))
#画一个矩形,必填参数为坐标,第一第二个为起始点坐标,第三第四个为终点坐标
draw.text((10, 10), Hello, fill=(255,0,0), font=None) #画文字,文本左上角为x y坐标数据

draw.line(((60,60),(90,60))) #画一条直线
draw.line(((60,60),(90,60), (90,90), (60,90), (60,60))) 
#画多条直线,每条线的起点坐标就是上一条线的终点坐标,此例子就是4条直线围成一个正方形

题目

[天翼杯 2021]rrrgggbbb

分别用StegSolve查看之后,发现分别r0、g0、b0通道的上方有像素点点。

抽出,发现``BPG头,并且有THE END`标志

需要把THE END标志及其之后的内容删掉

from PIL import Image
r=Image.open("rrr.png")
g=Image.open("ggg.png")
b=Image.open("bbb.png")

height = r.height
width = r.width

r_list = ""
g_list = ""
b_list = ""
for y in range(height):
    for x in range(width):
        r_list += bin(r.getpixel((x, y))[0])[2:].zfill(8)[7]
        g_list += bin(g.getpixel((x, y))[1])[2:].zfill(8)[7]                   
        b_list += bin(b.getpixel((x, y))[2])[2:].zfill(8)[7]
 
out=open('out1.bpg','wb')
for i in range (0, len(r_list), 8):    
    out.write(int(r_list[i:i+8],2).to_bytes(length=1,byteorder='big'))
    out.write(int(g_list[i:i+8],2).to_bytes(length=1,byteorder='big'))    
    out.write(int(b_list[i:i+8],2).to_bytes(length=1,byteorder='big'))
   
out.close()
r.close()
g.close()
b.close()

删去END后面的内容即可得到flag

Matplotlib Pyplot

Pyplot 是matplotlib的子库。

Pyplot 包含一系列绘图函数的相关函数,每个函数会对当前的图像进行一些修改,例如:给图像加上标记,生新的图像,在图像中产生新的绘图区域等等。

import matplotlib.pyplot as plt

引入pyplot库 ,设置别名为plt。

  • plot():用于绘制线图和散点图
  • scatter():用于绘制散点图
  • bar():用于绘制垂直条形图和水平条形图
  • hist():用于绘制直方图
  • pie():用于绘制饼图
  • imshow():用于绘制图像
  • subplots():用于创建子图
# 画单条线
plot([x], y, [fmt], *, data=None, **kwargs)
# 画多条线
plot([x], y, [fmt], [x2], y2, [fmt2], ..., **kwargs)
plot(x, y)     # 创建 y 中数据与 x 中对应值的二维线图,使用默认样式
plot(x, y, 'bo') # 创建 y 中数据与 x 中对应值的二维线图,使用蓝色实心圈绘制
plot(y)      # x 的值为 0..N-1
plot(y, 'r+')   # 使用红色 + 号

颜色字符:‘b’ 蓝色,‘m’ 洋红色,‘g’ 绿色,‘y’ 黄色,‘r’ 红色,‘k’ 黑色,‘w’ 白色,‘c’ 青绿色,‘#008000’ RGB 颜色符串。多条曲线不指定颜色时,会自动选择不同颜色。

线型参数:‘‐’ 实线,‘‐‐’ 破折线,‘‐.’ 点划线,‘:’ 虚线。

标记字符:‘.’ 点标记,‘,’ 像素标记(极小点),‘o’ 实心圈标记,‘v’ 倒三角标记,‘^’ 上三角标记,‘>’ 右三角标记,‘<’ 左三角标记…等等。

绘制直线时

import matplotlib.pyplot as plt
import numpy as np # 引入多维数组
x=np.array([0,6])
y=np.array([0,100])
plt.plot(x,y)
plt.show

只想绘制两个点

import matplotlib.pyplot as plt
import numpy as np # 引入多维数组
x=np.array([0,6])
y=np.array([0,100])
plt.plot(x,y,'o')
plt.show

如果不指定x的值,那么将会根据y的值来设置

我们可以使用 pyplot 中的 grid() 方法来设置图表中的网格线。

matplotlib.pyplot.grid(b=None, which='major', axis='both', )
//b:可选,默认为 None,可以设置布尔值,true 为显示网格线,false 为不显示,如果设置 kwargs 参数,则值为 true。
标题和轴标签

        设置图片标题:

plt.title("标题", fontsize=12, loc="center")//loc:left, right, center
        设置轴标签:

plt.xlabel("x轴标题", fontsize=12, loc="left")//loc: left, right, center
plt.ylabel("y轴标题", fontsize=12, loc="top")//loc: top, bottom, center


设置横坐标轴刻度范围:plt.xticks(ticks, labels, rotation=90, fontsize=12)
设置纵坐标轴刻度范围:plt.yticks(ticks, labels, rotation=90, fontsize=12)

绘制多图

subplot() 方法在绘图时需要指定位置,subplots() 方法可以一次生成多个,在调用时只需要调用生成对象的 ax 即可。

import matplotlib.pyplot as plt
import numpy as np

#plot 1:
xpoints = np.array([0, 6])
ypoints = np.array([0, 100])

plt.subplot(1, 2, 1)
plt.plot(xpoints,ypoints)
plt.title("plot 1")

#plot 2:
x = np.array([1, 2, 3, 4])
y = np.array([1, 4, 9, 16])

plt.subplot(1, 2, 2)
plt.plot(x,y)
plt.title("plot 2")

plt.suptitle("RUNOOB subplot Test")
plt.show()

subplots()

matplotlib.pyplot.subplots(nrows=1, ncols=1, *, sharex=False, sharey=False, squeeze=True, subplot_kw=None, gridspec_kw=None, fig_kw)
  • nrows:默认为 1,设置图表的行数。
  • ncols:默认为 1,设置图表的列数。
  • sharex、sharey:设置 x、y 轴是否共享属性,默认为 false,可设置为 ‘none’、‘all’、‘row’ 或 ‘col’。 False 或 none 每个子图的 x 轴或 y 轴都是独立的,True 或 ‘all’:所有子图共享 x 轴或 y 轴,‘row’ 设置每个子图行共享一个 x 轴或 y 轴,‘col’:设置每个子图列共享一个 x 轴或 y 轴。
  • squeeze:布尔值,默认为 True,表示额外的维度从返回的 Axes(轴)对象中挤出,对于 N1 或 1N 个子图,返回一个 1 维数组,对于 N*M,N>1 和 M>1 返回一个 2 维数组。如果设置为 False,则不进行挤压操作,返回一个元素为 Axes 实例的2维数组,即使它最终是1x1。
  • subplot_kw:可选,字典类型。把字典的关键字传递给 add_subplot() 来创建每个子图。
  • gridspec_kw:可选,字典类型。把字典的关键字传递给 GridSpec 构造函数创建子图放在网格里(grid)。
  • **fig_kw:把详细的关键字参数传给 figure() 函数。
import matplotlib.pyplot as plt
import numpy as np
# 创建一个2x2的子图
fig, axs = plt.subplots(nrows=2, ncols=2)
 
# 在第一个子图中绘制正弦函数
x = np.linspace(0, 10, 100)
y1 = np.sin(x)
axs[0, 0].plot(x, y1)
axs[0, 0].set_title('Sin(x)')
 
# 在第二个子图中绘制余弦函数
y2 = np.cos(x)
axs[0, 1].plot(x, y2)
axs[0, 1].set_title('Cos(x)')
 
# 在第三个子图中绘制正切函数
y3 = np.tan(x)
axs[1, 0].plot(x, y3)
axs[1, 0].set_title('Tan(x)')
 
# 在第四个子图中绘制正切函数的导数
y4 = 1 / np.cos(x) ** 2
axs[1, 1].plot(x, y4)
axs[1, 1].set_title('Tan\'(x)')
# 调整布局以及子图之间的间距
plt.tight_layout()
# 显示图形
plt.show()
//
第 8~13 行在第一个子图 axs[0,0] 中绘制正弦函数,同时设置了标题为 ‘Sin(x)’。

第 16~21 行在第二个子图 axs[0,1] 中绘制余弦函数,同时设置了标题为 ‘Cos(x)’。

第 24~29 行在第三个子图 axs[1,0] 中绘制正切函数,同时设置了标题为 ‘Tan(x)’。

第 32~37 行在第四个子图 axs[1,1] 中绘制正切函数的导数,同时设置了标题为 ‘Tan’(x)'。

散点图

可以用plot或scatter

import numpy as np
import matplotlib.pyplot as plt

height=[160,170,175,186]
weight=[49,50,55,58]
plt.scatter(heigth,weight)   #将x和y的数据变成列表
plt.show()

折线图

import numpy as np
import matplotlib.pyplot as plt

x=np.linspace(-10,10,100) #从-10到10,等区间分成100份
y=x**2
plt.plot(x,y)
plt.show()


import matplotlib.pyplot as plt
import numpy as np 
x=np.array([1,0,2,6])
y=np.array([0,100,12,2])
plt.plot(x,y)
plt.show()

条形图

import numpy as np
import matplotlib.pyplot as plt

#------绘制单变量条形图------
n=5
y=[10,20,40,5060]
index=np.arrage(n)
pl=plt.bar(left=index,height=y,color='red',width=0.5)  #left表示横坐标从0到5,高度为y,颜色为红色,宽度为0.5
pl=plt.bar(left=0,bottow=index,width=y,color='red',height=0.5,orientation='horizontal')  #left表示横坐标,bottow表示纵坐标,width表示宽度,颜色为红色,高度为0.5,方向为水平方向
plt.show()

#多变量条形图
sales_BJ=[50,55,63,69]
sales_SH=[45,56,58,66]

#绘制并列式的条形图
plt.bar(left=index,height=sales_BJ,colors='red')
plt.bar(left=index+barwidth,height=sales_SH,colors='blue')  
plt.show()

直方图

import numpy as np
import matplotlib.pyplot as plt

#-------绘制单变量直方图-------
x=100+no.random.randon(2000)  #x是2000个以100为均值的随机数据
plt.hist(x,bins=10,normed=True)   #bins表示共有10个直方块,normed表示是否需要标准化数据
plt.show()

#-------绘制双变量直方图-------
x=np.random.randon(2000)+2
y=np.random.randon(2000)+3
plt.hist2d(x,y,bins=40)   #用颜色深浅表示频率的大小
plt.show()

饼状图

import numpy as np
import matplotlib.pyplot as plt

labels='A','B','C','D'
fracs=[15,30,45,10]
explode=[0,0.05,0,0]   #标签为B的饼块将会离开圆心0.05个距离单位
plt.axes(aspect=1)   #绘制正圆
plt.pie(x=fracs,labels=labels,autopct='%.0f%%',explode=explode,shadow=True)  #autopct表示数据将会精确到小数点后一位,expolde表示希望着重表示哪一块,shadow表示是否需要添加阴影显得更好看
plt.show()

imshow()

imshow() 函数是 Matplotlib 库中的一个函数,用于显示图像。

imshow() 函数常用于绘制二维的灰度图像或彩色图像。

imshow() 函数可用于绘制矩阵、热力图、地图等。

imshow(X, cmap=None, norm=None, aspect=None, interpolation=None, alpha=None, vmin=None, vmax=None, origin=None, extent=None, shape=None, filternorm=1, filterrad=4.0, imlim=None, resample=None, url=None, *, data=None, kwargs)
绘画矩阵
x = [[1,2],[3,4]]
plt.imshow(x, cmap=plt.cm.gray, alpha=0.5)
plt.text(0, 0, "TP")
plt.text(0, 1, "FP")
plt.text(1, 0, "FN")
plt.text(1, 1, "TN")
plt.xlabel("prediction")
plt.ylabel("label")
plt.xticks([0, 1], ["true", "false"])
plt.yticks([0, 1], ["true", "false"])
//生成与x的形状相同的方块矩阵,与x的内部值没关系,只与其形状有关系
//alpha设置透明度

imread

imread() 方法是 Matplotlib 库中的一个函数,用于从图像文件中读取图像数据。可以裁剪图像,也可以改变图像的颜色。

imread() 方法返回一个 numpy.ndarray 对象,其形状是 (nrows, ncols, nchannels),表示读取的图像的行数、列数和通道数:

  • 如果图像是灰度图像,则 nchannels 为 1。
  • 如果是彩色图像,则 nchannels 为 3 或 4,分别表示红、绿、蓝三个颜色通道和一个 alpha 通道。

imread() 方法的语法如下:

matplotlib.pyplot.imread(fname, format=None)
fname:指定了要读取的图像文件的文件名或文件路径,可以是相对路径或绝对路径。
format :参数指定了图像文件的格式,如果不指定,则默认根据文件后缀名来自动识别格式。
import matplotlib.pyplot as plt

# 读取图像文件,下载地址:
img = plt.imread('map.jpeg')

# 显示图像
plt.imshow(img)
plt.show()

ciscn2023的国粹

根据第一张麻将的图片进行从1开始标记,然后以a.png为横坐标,另一个为纵坐标。

import matplotlib.pyplot as plt
x = [1,1,1,1,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,6,6,6,6,6,6,6,6,6,6,6,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,8,8,8,8,8,8,8,8,8,8,8,8,8,9,9,9,9,9,9,10,10,12,12,12,12,13,13,13,13,13,13,13,13,13,13,13,13,13,13,14,14,14,14,14,14,14,14,15,15,15,15,15,15,15,16,16,16,16,16,16,16,16,17,17,17,17,17,17,17,17,18,18,18,18,18,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,20,22,22,22,22,22,22,22,22,22,22,22,22,23,23,23,23,23,23,23,23,23,23,23,23,23,24,24,24,24,24,24,24,24,24,24,25,25,25,25,25,25,25,25,25,25,25,26,26,26,26,26,26,26,26,26,26,27,27,27,27,27,27,27,27,27,27,27,28,28,28,28,28,28,28,28,28,28,28,28,28,29,29,29,29,29,31,31,31,31,31,31,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,33,33,33,33,33,33,33,33,33,33,33,34,34,34,34,34,34,34,34,34,35,35,35,35,35,35,35,35,35,35,35,36,36,36,36,36,36,36,37,37,37,37,37,37,37,37,37,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,39,39,39]
y = [4,5,10,10,30,3,4,5,6,10,29,30,3,4,10,16.17,22,23,24,25,29,30,2,3,4,5,10,15,16,18,21,22,24,25,29,30,3,4,10,15,17,18,19,21,22,25,28,29,3,4,10,15,16,18,19,21,22,25,29,34,10,11,12,13,15,18,19,22,23,24,25,29,30,3,4,11,12,15,16,17,18,19,20,25,29,30,20,21,23,24,30,31,22,24,22,23,24,25,2,3,3,4,9,10,11,12,16,17,18,19,24,25,2,5,6,9,12,18,22,23,5,9,12,18,19,22,23,4,5,9,12,17,18,23,24,3,4,9,12,16,17,24,25,3,9,12,16,25,3,4,5,6,9,10,11,12,16,17,18,19,21,22,23,24,25,10,11,3,4,5,6,10,11,12,17,18,19,24,25,3,6,7,9,10,16,17,19,20,22,23,24,25,3,6,7,9,10,15,18,19,23,24,3,6,7,10,11,12,16,19,20,24,25,3,6,7,12,13,16,19,20,24,25,3,6,7,9,12,13,16,19,20,24,25,3,4,6,9,10,11,12,16,17,19,20,24,25,4,5,17,18,19,10,11,12,13,25,31,4,5,6,10,11,12,13,17,18,19,23,24,25,26,32,3,4,5,6,7,12,16,17,23,24,26,32,6,7,11,16,17,23,24,26,32,6,11,12,17,18,19,23,24,25,26,33,5,12,13,19,20,26,32,4,5,13,16,19,20,25,26,32,4,5,6,7,9,10,11,12,13,16,17,18,19,24,25,31,32,23,24,31]

plt.plot(x,y,'rH')
plt.show()

绘图得到