我觉得我的女神很漂亮,想把她的照片当成图表背景,该怎么做?(新篇)

我觉得我的女神很漂亮,想把她的照片当成图表背景,该怎么做?(新篇)

在一年前的寒假我刚刚学习用 Stata 绘图的时候就做过这么一件事情:画图片,当时的结果不是很成功,画出来的照片看起来很“水墨风格”???详细绘图方法可以参考:我觉得我的女神很漂亮,想把她的照片当成图表背景,该怎么做?

当时画出来的图片是这样的:

最近看到一篇公众号文章:用 Stata 画出黄家驹——以及实现像素级的操作,也讲了如何用 Stata 画照片。

原理很简单,是先用其它软件把照片转换成 Stata 可以处理的数据,然后在绘制精细的散点图,假如我想绘制这幅图:

先用 Python 将照片处理成 csv 文件:

Python
1
2
3
4
5
6
7
import numpy as np
import pandas as pd
from PIL import Image
img = Image.open('WechatIMG35.jpeg')
a = np.array(img.convert('L'))
df = pd.DataFrame(a)
df.to_csv('photo.csv')

这段代码我保存为 img2csv.py 文件:

然后是 Stata 部分:

Stata
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
!/anaconda3/bin/python img2csv.py
clear all
import delimited photo.csv, clear
/* 删除 pandas 数据框的行索引和列索引 */
drop in 1
drop v1
* 对于每一个变量除以25,然后取整,就将像素点的灰度范围从0~255变成0~10。
* 也就是说,原来灰度为255的等同于现在的10。
forval i = 2/1441{
replace v`i' = int(v`i' / 25)
}
stack v2 - v1441, into(v) clear // 将数据堆积成一列
rename _stack x // 产生x坐标
gen y = mod(_n-1, 1080) // 对于行数取余,产生y坐标
gsort v
drop if v == 10 // 灰度值为10的就是白色,可以不用画白色,删掉之
gen yy = -y // 图片采用的笛卡尔坐标系,与我们日常用的二维坐标系y轴相反
tw ///
sc yy x if v == 9, msize(vtiny) mc(black*0.1%10) || ///
sc yy x if v == 8, msize(vtiny) mc(black*0.2%10) || ///
sc yy x if v == 7, msize(vtiny) mc(black*0.3%10) || ///
sc yy x if v == 6, msize(vtiny) mc(black*0.4%10) || ///
sc yy x if v == 5, msize(vtiny) mc(black*0.5%10) || ///
sc yy x if v == 4, msize(vtiny) mc(black*0.6%10) || ///
sc yy x if v == 3, msize(vtiny) mc(black*0.7%10) || ///
sc yy x if v == 2, msize(vtiny) mc(black*0.8%10) || ///
sc yy x if v == 1, msize(vtiny) mc(black*0.9%10) || ///
sc yy x if v == 0, msize(vtiny) mc(black%10) ///
ytitle("") ///
xtitle("") ///
ylabel("") ///
xlabel("") ///
legend(off) ///
aspect(1) ///
scheme(s1color)

绘制出来的是一张比较模糊的黑白图片:

我还尝试了绘制彩色图片,但是多次尝试的结果表明效果不好。我是先使用 R 将照片转换成三个 csv 文件,分别是 R、G、B 三个图层,然后重叠绘制,同时考虑到图层之间的重叠,我为每个图层设置了 3% 的透明度,因为总共要绘制 10 * 3 = 30 个图层。

Stata
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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
clear all
rcall: ///
df <- jpeg::readJPEG('WechatIMG35.jpeg'); ///
matrix(df[1:(1080*1440)], nrow = 1080, ncol = 1440) %>% as_tibble() %>% readr::write_csv("photo1.csv"); ///
matrix(df[((1080*1440)+1):(1080*1440*2)], nrow = 1080, ncol = 1440) %>% as_tibble() %>% readr::write_csv("photo2.csv"); ///
matrix(df[((1080*1440*2) + 1) : (1080*1440*3)], nrow = 1080, ncol = 1440) %>% as_tibble() %>% readr::write_csv("photo3.csv")

forval m = 1/3{
clear all
import delimited photo`m'.csv, clear
forval i = 1/1440{
replace v`i' = int(v`i' * 10)
}

stack v1 - v1440, into(v) clear // 将数据堆积成一列
rename _stack x // 产生x坐标
gen y = mod(_n-1, 1080) // 对于行数取余,产生y坐标
gsort v
drop if v == 10 // 灰度值为10的就是白色,可以不用画白色,删掉之
gen yy = -y // 图片采用的笛卡尔坐标系,与我们日常用的二维坐标系y轴相反
gen color = `m'
save `m', replace
}

clear all
use 1, clear
append using 2
append using 3

local color2 = "green"
local color3 = "blue"
local color1 = "red"

tw ///
sc yy x if v == 9 & color == 1, msize(vtiny) mc(`color1'*0.1%3) || ///
sc yy x if v == 9 & color == 2, msize(vtiny) mc(`color2'*0.1%3) || ///
sc yy x if v == 9 & color == 3, msize(vtiny) mc(`color3'*0.1%3) || ///
sc yy x if v == 8 & color == 1, msize(vtiny) mc(`color1'*0.2%3) || ///
sc yy x if v == 8 & color == 2, msize(vtiny) mc(`color2'*0.2%3) || ///
sc yy x if v == 8 & color == 3, msize(vtiny) mc(`color3'*0.2%3) || ///
sc yy x if v == 7 & color == 1, msize(vtiny) mc(`color1'*0.3%3) || ///
sc yy x if v == 7 & color == 2, msize(vtiny) mc(`color2'*0.3%3) || ///
sc yy x if v == 7 & color == 3, msize(vtiny) mc(`color3'*0.3%3) || ///
sc yy x if v == 6 & color == 1, msize(vtiny) mc(`color1'*0.4%3) || ///
sc yy x if v == 6 & color == 2, msize(vtiny) mc(`color2'*0.4%3) || ///
sc yy x if v == 6 & color == 3, msize(vtiny) mc(`color3'*0.4%3) || ///
sc yy x if v == 5 & color == 1, msize(vtiny) mc(`color1'*0.5%3) || ///
sc yy x if v == 5 & color == 2, msize(vtiny) mc(`color2'*0.5%3) || ///
sc yy x if v == 5 & color == 3, msize(vtiny) mc(`color3'*0.5%3) || ///
sc yy x if v == 4 & color == 1, msize(vtiny) mc(`color1'*0.6%3) || ///
sc yy x if v == 4 & color == 2, msize(vtiny) mc(`color2'*0.6%3) || ///
sc yy x if v == 4 & color == 3, msize(vtiny) mc(`color3'*0.6%3) || ///
sc yy x if v == 3 & color == 1, msize(vtiny) mc(`color1'*0.7%3) || ///
sc yy x if v == 3 & color == 2, msize(vtiny) mc(`color2'*0.7%3) || ///
sc yy x if v == 3 & color == 3, msize(vtiny) mc(`color3'*0.7%3) || ///
sc yy x if v == 2 & color == 1, msize(vtiny) mc(`color1'*0.8%3) || ///
sc yy x if v == 2 & color == 2, msize(vtiny) mc(`color2'*0.8%3) || ///
sc yy x if v == 2 & color == 3, msize(vtiny) mc(`color3'*0.8%3) || ///
sc yy x if v == 1 & color == 1, msize(vtiny) mc(`color1'*0.9%3) || ///
sc yy x if v == 1 & color == 2, msize(vtiny) mc(`color2'*0.9%3) || ///
sc yy x if v == 1 & color == 3, msize(vtiny) mc(`color3'*0.9%3) || ///
sc yy x if v == 0 & color == 1, msize(vtiny) mc(`color1'%3) || ///
sc yy x if v == 0 & color == 2, msize(vtiny) mc(`color2'%3) || ///
sc yy x if v == 0 & color == 3, msize(vtiny) mc(`color3'%3) ///
ytitle("") ///
xtitle("") ///
ylabel("") ///
xlabel("") ///
legend(off) ///
aspect(1) ///
scheme(s1color)

结果很糟糕,我又改变了几次颜色叠加的顺序,效果不大:

看了 Stata 画图片还是不行。

为了方便,我们可以把这些操作整理成一个 Stata 命令,考虑到彩色图片画的并不好而且费时间,我们还是绘制黑白图片吧:

Stata
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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
capture program drop plotimg
program define plotimg
syntax anything(name = img) [, ASPECTratio(real 1)]
di "处理图片中......"
qui{
file open myfile using img2csv.py, write replace
file write myfile `"import numpy as np"' _n
file write myfile `"import pandas as pd"' _n
file write myfile `"from PIL import Image"' _n
file write myfile `"img = Image.open('`img'')"' _n
file write myfile `"a = np.array(img.convert('L'))"' _n
file write myfile `"df = pd.DataFrame(a)"' _n
file write myfile `"df.to_csv('photo.csv')"' _n
file close myfile
!/anaconda3/bin/python img2csv.py
import delimited photo.csv, clear
drop in 1
drop v1
qui count
local nrow = `r(N)'
qui ds
local ncol = wordcount("`r(varlist)'")
local ncol2 = `ncol' + 1
forval i = 2/`ncol2'{
replace v`i' = int(v`i' / 25)
}
stack v2 - v`ncol2', into(v) clear // 将数据堆积成一列
rename _stack x // 产生x坐标
gen y = mod(_n-1, `nrow') // 对于行数取余,产生y坐标
gsort v
drop if v == 10 // 灰度值为10的就是白色,可以不用画白色,删掉之
gen yy = -y // 图片采用的笛卡尔坐标系,与我们日常用的二维坐标系y轴相反
}
di "绘图中......"
qui{
tw ///
sc yy x if v == 9, msize(vtiny) mc(black*0.1) || ///
sc yy x if v == 8, msize(vtiny) mc(black*0.2) || ///
sc yy x if v == 7, msize(vtiny) mc(black*0.3) || ///
sc yy x if v == 6, msize(vtiny) mc(black*0.4) || ///
sc yy x if v == 5, msize(vtiny) mc(black*0.5) || ///
sc yy x if v == 4, msize(vtiny) mc(black*0.6) || ///
sc yy x if v == 3, msize(vtiny) mc(black*0.7) || ///
sc yy x if v == 2, msize(vtiny) mc(black*0.8) || ///
sc yy x if v == 1, msize(vtiny) mc(black*0.9) || ///
sc yy x if v == 0, msize(vtiny) mc(black) ///
ytitle("") ///
xtitle("") ///
ylabel("") ///
xlabel("") ///
legend(off) ///
aspect(`aspectratio') ///
scheme(s1color)
}
end // end of program plotimg

使用:

Stata
1
plotimg WechatIMG13177.jpeg

Stata
1
plotimg WechatIMG13177.jpeg, aspect(1.2)

原图:

Stata
1
plotimg WechatIMG38.jpeg

原图:

Stata
1
plotimg WechatIMG37.jpeg

原图:

# Stata

Comments

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×