”一“的客观形态与主观感受之间的关联性研究
目录
”一“的客观形态与主观感受之间的关联性研究
概述
逻辑上而言,每个”一“的感受都来源于其形态,那么我们不禁要问,各个”一“带来的不同感受与它们的形态有何关联呢?为了探索”形态-感受“的关联性,需要对每个”一“的客观造型进行描述,提取特征,这里就需要用到图像处理的技术了。
研究主题与内容
研究主题
针对”一“,定义一系列特征(可借鉴参考资料),并依此对每个”一“进行测量。测量可以分两个层次:
- 手工测量
- 用算法实现测量
研究内容
- 至少定义5个特征,需要图文结合地清晰描述出这些特征的定义
- 至少要能够手工方式对十二个”一“测定所有定义好的特征
- 尽可能用算法实现测量,并对比手工测量的结果
特征定义
长度
不同书法家因其书写习惯的影响,在宽度和长度上会一定的区别,笔划长度 L 用来表现笔划基元的骨架规模,统计笔划骨架的初始像素点到该笔划的另一个结束像素点这个过程中所有像素点的个数,像素点集B=(b1,b2,
…,bn),则用像素点的总个数来表示笔划的长度特征。
走势
根据笔划骨架起始点坐标位置和结束点坐标位置,可以得到每个笔划的走势情况。书法家张旭因其笔划走势夸张而闻名,笔划走势定义为:
正向相对扰动度
见 正向最大扰动度点相对位置
正向最大扰动度点相对位置
面积
面积为我自己定义的特征,这里指图像经过二值化处理后,去除离散区域并填充孔洞后,笔划的所有像素点数。
周长
周长为我自己定义的特征,这里指图像经过二值化处理后,去除离散区域并填充孔洞后,经过边缘检测,计算所有像素点的个数。
重心位置
书法字符图像中包含着丰富的信息,宽 扁的书法字符几何重心偏低,瘦高的书法字符几何重心偏高。书法骨架矩阵 g(i,j),书法字的重心位置为 a8 (x,y)定义为:
黑白二值比
二值化图像为 MxN像素点 ,(x,y)为坐标 ,P(x,y)表示二值图像像素点:
手工测量
因为我觉得用尺子测量没有什么意义,所以这边选择的是用系统自带的画图工具,然后调整并肉眼观察数据,也算是一种手工测量的方法(因为数据肯定没有用程序算出来那么精确),过程这边就省略了,直接放出结果。
下表为能手工测了出来的特征(都为大概的结果):
长度 | 走势 | 正向扰动度 | 正向最大扰动度点相对位置 | 面积 | 周长 | 重心位置 | 黑白二值比 | |
---|---|---|---|---|---|---|---|---|
A | 557 | -0.082 | null | null | 22054 | 1182 | (204,303) | null |
B | 602 | 25.87 | null | null | 20046 | 1278 | (230,289) | null |
C | 800 | -8.35 | null | null | 23598 | 1302 | (220,309) | null |
D | 823 | 192 | null | null | 28387 | 1626 | (232,338) | null |
E | 592 | -8.32 | null | null | 25632 | 982 | (251,270) | null |
F | 622 | -20 | null | null | 19864 | 894 | (238,300) | null |
G | 986 | -102.34 | null | null | 16234 | 1143 | (200,330) | null |
H | 701 | -15.4 | null | null | 26956 | 1247 | (220,287) | null |
I | 762 | -14.23 | null | null | 32214 | 1278 | (244,323) | null |
J | 803 | 15.87 | null | null | 31074 | 1469 | (230,307) | null |
K | 583 | 20.34 | null | null | 24763 | 1292 | (224,323) | null |
L | 765 | 8.39 | null | null | 17326 | 1256 | (222,342) | null |
算法实现测量
实验流程
读取图片并直接灰度化
im = cv2.imread(im_path, 0)
im_path指定图片路径,0代表直接将图片灰度化
]
二值化
im = Two(im)
Two函数为自己简单写的一个二值化函数,指定一个阈值大于该阈值为255,小于为0
颜色反转
im = cv2.bitwise_not(im)
bitwise_not函数即对图像取反,0变255,255变0。
去除离散区域
contours, hierarch = cv2.findContours(image, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
for i in range(len(contours)):
area = cv2.contourArea(contours[i])
if area < areaSize:
cv2.drawContours(image, [contours[i]], 0, 0, -1)
-
findContours用于检测一幅图像中的所有轮廓。
参数1指定要处理的图像
参数2指定轮廓的检索模式,这边使用的是检测外轮廓
参数3指定轮廓的近似方法,这边为存储所有的轮廓点,相邻的两个点的像素位置差不超过1
返回值1为轮廓本身,为一个List列表
返回值2为轮廓的属性
-
contourArea主要用于计算轮廓的近似面积
-
drawContours用于绘制轮廓
参数1指定要处理的图像
参数2指定为哪个轮廓列表
参数3指定为轮廓列表的哪个轮廓
参数4指定绘制的轮廓颜色
参数5指定绘制线型,为负数的话则为填充模式
-
整个代码块表示在图像中找到所有轮廓区域,并将面积小于200的轮廓进行填充,这样就达到去除离散区域的目的。
填充孔洞
def FillHole_function(image):
im_in = image
im_floodfill = im_in.copy()
h, w = im_in.shape[:2]
mask = np.zeros((h + 2, w + 2), np.uint8)
isbreak = False
for i in range(im_floodfill.shape[0]):
for j in range(im_floodfill.shape[1]):
if (im_floodfill[i][j] == 0):
seedPoint = (i, j)
isbreak = True
break
if (isbreak):
break
cv2.floodFill(im_floodfill, mask, seedPoint, 255);
im_floodfill_inv = cv2.bitwise_not(im_floodfill)
im_out = im_in | im_floodfill_inv
return im_out
-
floodfill为种子填充法对目标图像进行填充
参数1指定要进行填充的图像
参数2指定填充图像的大小,这边的mask为h+2,w+2的二维矩阵则是对整个图像进行填充
参数3指定要填充的颜色
-
fillHole函数通过找到第一个为0的像素点即黑色像素点对整个图像进行填充,填充之后进行反相,反相后将处理后的图片与原图片进行或操作,就可以得到一副已经填充孔洞的图像。
提取骨架
def getSkeleton(image):
i=0
element = cv2.getStructuringElement(cv2.MORPH_CROSS, (3, 3))
skel = np.zeros(image.shape, np.uint8)
while True:
i=i+1
erode = cv2.erode(image, element)
temp = cv2.dilate(erode, element)
temp = cv2.subtract(image, temp)
skel = cv2.bitwise_or(skel, temp)
image = erode.copy()
if cv2.countNonZero(image) == 0:
break;
return skel
-
getStructuringElement函数会返回指定形状和尺寸的结构元素。
参数1为内核的形状,这里是交叉性,也就是老师讲腐蚀与膨胀时的交叉型
参数2为内核的大小,这里是3*3的
返回值为这个结构本身,这里是3*3的交叉性矩阵
-
erode函数用于对图像进行腐蚀
参数1为图像本身
参数2为结构元素
返回值为图像
-
dilate函数用于对图像进行膨胀
参数1为图像本身
参数2为结构元素
返回值为图像
-
原理
每次迭代图像都会再次腐蚀,经过腐蚀后物体变得更窄细,对腐蚀后图像做开运算,经过开运算后处理后,图像有些像素会被删除,这些被删除的像素其实是骨架的一部分,将删除的像素添加到骨架图上,当腐蚀后图像没有像素后,就结束迭代,这时候或生成的骨架图也就完整了。
-
参考
http://felix.abecassis.me/2011/09/opencv-morphological-skeleton/
https://en.wikipedia.org/wiki/Morphological_skeleton
UI界面
测量结果
见附data.csv文件。
总结
和律老师给的酸甜苦辣高兴,悲伤什么的统计数据进行了比较一下,真的没有发现有什么联系,就连最能关系到的密度属性也没看出内在关系,然后就按照对比图看了几个最容易看出的属性。
-
从数据上来看,一般周长越大的字,面积越大,同样在图中也可以看出面积很大,多呈现较粗的趋势。
-
一般骨架长度越大的字就越显得修长,比如G等。
-
一般来看笔势为正,字会有向下弯曲的趋势,当然也有特例。
-
所有字的重心位置都几乎在中间。
-
正向最大扰动度大于1的边缘处都比较绕,就是有一个回弯
-
正向最大扰动度点相对位置越大的,说明最远点到直线的垂线的相交位置已经跨过骨架,I,J,K,G这几幅图相对位置都比较大。
下一篇: Tensorflow构建卷积神经网络