项目四地学文献中三角图和知识图谱关联:
春来我不先开口,哪个虫儿敢作声。这个项目目前我参加最大的项目是国家自然科学基金指南引导类0-1原创探索项目子课题,(“沉积物知识图谱及其知识演化研究”)。这个小妙点子只是这个项目其中的一部分,在前期很紧急的情况下,也是第一个将知识图谱和沉积学实实在在关联到一起的例子。
项目需求分析
已知砂岩的体系结构和不同研究人员对同一个石头命名标准和名词的不同。在有关砂岩的文献中经常会出现一种图,叫做三角图,三角图记录着砂岩中FQL三种岩性的含量,由于含量不同就会呈现不同种类的砂岩。现在需要将两种已经的条件结合,做出项目需求,知识图谱和文本内三角图中各个已知点的关联。
砂岩知识图谱构建:
由于是给地学领域的学家构建图谱,他们本身对计算机软件编程学习量少,也由于时间紧任务重问题。我们这无法开发一个让他们自己填节点和关系的前后端软件,这也不是项目的需求,如何快速且能够让地学家上手,首先想到的是neo4j里面的import文件夹,可以导入CSV这样只要告诉地学家如何按照neo4j要求放入节点和边就好了。如图所示
具体构建代码其实很简单只要将同类父类放入一个csv表,上下级父子关系放入一个csv文件夹,这边特别注意一下file://代表了文件前面一系列的相对路径,后面直接写自己在import文件夹下的文件名,例如我就是创建了newtest文件夹如下所示:
//创建standstone结点
//导入节点 总石头类型 == 注意类型转换
LOAD CSV WITH HEADERS FROM "file:///newtest///standstone.csv" AS line
MERGE (p:StandStone{
sid:toInteger(line.sid),name:line.sname,definition:line.sdefinition,references:line.sreferences})
return p
//导入节点 二级石头类型 == 注意类型转换
LOAD CSV WITH HEADERS FROM "file:///newtest///standclassfion.csv" AS line
MERGE (p:StandStoneclassfion{
ssid:toInteger(line.ssid),name:line.ssname})
return p
//5
// 导入关系 classification Standstone被二级分类
LOAD CSV WITH HEADERS FROM "file:///newtest///standstone_to_standclassfion.csv" AS line
match (from:StandStone{
sid:toInteger(line.sid)}),(to:StandStoneclassfion{
ssid:toInteger(line.ssid)})
merge (from)-[r:classification{
sid:toInteger(line.sid),ssid:toInteger(line.ssid)}]->(to)
PDF中三角图识别方案:
解决了知识图谱的问题,那么就开始解决PDF中三角图的问题,我们需要运用到OpenCV包,首先将每页PDF都转成png形式,代码如下:
import fitz
import os
import cv2
from PIL import Image
from io import BytesIO
import numpy as np
"""
输入: pdf文件路径
输出: pdf按页截图的列表
"""
def pdf_to_cv2img_list(pdf_path):
pdf = fitz.open(pdf_path)
cv2img_list = []
for pg, page in enumerate(pdf):
# 缩放系数
zoom = 2
mat = fitz.Matrix(zoom, zoom)
pix = page.getPixmap(matrix=mat, alpha=False) # alpha = 是否使用透明背景
pix1 = fitz.Pixmap(pix, 0) if pix.alpha else pix
img_data = pix1.getImageData("png")
bytes_stream = BytesIO(img_data)
img = Image.open(bytes_stream)
# img.show() # 通过系统默认方式打开图片
cv2img = cv2.cvtColor(np.asarray(img), cv2.COLOR_RGB2BGR)
cv2img_list.append(cv2img)
return cv2img_list
if __name__ == "__main__":
doc_dir = r'documents/'
doc_list = os.listdir(doc_dir)
print('文件列表:', doc_list)
print('文件数量:', len(doc_list))
for i, doc_name in enumerate(doc_list):
if doc_name[-4:].lower() == r'.pdf':
pdf_path = doc_dir + doc_name
# pdf_name = doc_name[:-4] # 删除末尾扩展名
# if len(pdf_name) > 50:
# pdf_name = pdf_name[:50].strip() # 截断过长文件名 去除可能的末尾空格 # 过长的文件名会导致保存失败 windows能接受的最长路径长度为255
print(i, ' ', doc_name)
cv2img_list = pdf_to_cv2img_list(pdf_path)
for i, img in enumerate(cv2img_list):
cv2.imshow('%s page:%d' % (doc_name, i+1), img)
cv2.waitKey(0)
cv2.destroyAllWindows()
else:
print("未知文件或目录:", doc_name)
紧接着,构建三角图,这里选取了三种人对三角图的定义:
# -*- coding: utf-8 -*-
import cv2
import numpy as np
img_g = cv2.imread(r'gfp/g.jpg')
g1, g2 = (2, 382), (409, 382)
img_f = cv2.imread(r'gfp/f1.png')
f1, f2 = (396, 630), (1041, 630) # (80, 423), (497, 423)
img_p = cv2.imread(r'gfp/p.jpg')
p1, p2 = (35, 245), (156, 245)
SQRT3 = np.sqrt(3)
SQRT3OVER2 = SQRT3 / 2.
def QFL2xy(QFL, scale):
b, c, a = QFL
a *= scale/100
b *= scale/100
c *= scale/100
x = a + b/2.
y = SQRT3OVER2 * b
# print(scale)
return x, y
def show(img, p1, p2, QFL, name):
scale = abs(p1[0]-p2[0])
o = p1
x0, y0 = QFL2xy(QFL, scale)
x, y = o[0]+x0, o[1]-y0
point = (int(x), int(y))
show_img = np.copy(img)
cv2.circle(show_img, point, 5, (0, 0, 200), thickness=-1)
# cv2.namedWindow(name)
# show_img = cv2.resize(show_img, (show_img.shape[1] // 2, show_img.shape[0] // 2))
if 'F' in name:
show_img = cv2.resize(show_img, None, fx=0.5, fy=0.5)
cv2.imshow(name, show_img)
def show_on_gfp(QFL)