关于个人项目进行化学图像识别的说明
- 原理说明:首先通过百度的ocr进行化学式的文字识别以及其坐标,进而实现官能团的识别以及位置构建
- 对全图进行扫描, 进而完整确定全图的结构。
- 将来可以引入ai,更高效便利实现图像识别
# coding=utf-8
from PIL import Image
from math import *
from aip import AipOcr
AppID = "25350322"
APIkey = "5tZwU0OWjz4ZOrhxLQWC6gvn"
SecretID = "AXloqKsHPGpXoNHGk5i8DxvrwVUIGT6D"
aipOcr = AipOcr(AppID, APIkey, SecretID)
def zhuaqu(filePath):
#filePath = "D:\\bf.jpg"
def get_file_content(filePath):
with open(filePath, 'rb') as fp:
return fp.read()
options = {
'detect_direction': 'true',
'language_type': 'CHN_ENG',
}
result = aipOcr.accurate(get_file_content(filePath), options)
return result["words_result"]
# print(result)
# words_result=result['words_result']
# for i in range(len(words_result)):
# print(words_result[i]['words'])
这是我利用百度ocr提供的文字识别代码写出的调用函数
接下来是化学式描图的主程序
这里描图的过程可以说是在一团毛线中找“线头”,当找到一个键线式的“线头”,那么接下来的工作就简单了:顺着这个线头向前即可。
from time import sleep
from PIL import Image
import numpy as np
import math
from huaxue1215 import zhuaqu
#定义区
Col = [(255, 0, 0), (0, 255, 0), (0, 0, 255), (255, 255, 0), (255, 0, 255), (0, 255, 255)]
pa = "D:\\化学俱乐部项目\\yangli2_NO23.jpg"
P = Image.open(pa)
Points = []
Used=np.zeros((max(P.height, P.width), max(P.height, P.width)))
#
def checktext(Tr, x, y): #判断像素是否在文字范围内
for i in Tr:
if (x >= i["location"]["left"]) and (x <= (i["location"]["left"] + i["location"]["width"])) and(y >= i["location"]["top"]) and (y <= (i["location"]["top"] + i["location"]["height"])):
return True
return False
#Zuobiao = [[1, 0], [-1, 0], [1, sqrt(3)], [-1, sqrt(3)]]
Lines = []
def Findnear(Po):#查找格子周围的点,R为半径
Ret = []
R = 5
for Y in range(Po[1]-R, Po[1]+R + 1):
if check(P.getpixel((Po[0] - R, Y))):
if Used[Po[0] - R, Y] != 1:
Ret.append((Po[0] - R, Y))
if check(P.getpixel((Po[0] + R, Y))):
if Used[Po[0] + R, Y] != 1:
Ret.append((Po[0] + R, Y))
for X in range(Po[0] - R + 1, Po[0] + R):
if check(P.getpixel((X, Po[1] - R))):
if Used[X, Po[1] - R] != 1:
Ret.append((X, Po[1] - R))
if check(P.getpixel((X, Po[1] + R))):
if Used[X, Po[1] + R] != 1:
Ret.append((X, Po[1] + R))
return Ret
#测试用
def dot(Mp, x, y, col):
for i in range(x - 2, x + 2):
for j in range(y - 2, y + 2):
Mp.putpixel((i, j), col)
Q = P#Image.new("RGB", (P.height, P.width), (255, 255, 255))
def check(x):
return ((x[0] < 128) & (x[1] < 128) & (x[2] < 128)) == True
#黑点
for i in range(P.width):
for j in range(P.height):
Point = P.getpixel((i, j))
if check(Point):
Points.append((i, j)) #抓取所有黑色像素,描边
# Q.putpixel((i, j), (0, 0, 0))
# print(Used)
# print(Points)
# Q.show()
T = zhuaqu(pa)
# print(T)
Tx = T[0]["location"]["left"] + T[0]["location"]["width"]
Ty = T[0]["location"]["top"] + T[0]["location"]["height"]
for i in T:
for X in range(i["location"]["left"], i["location"]["left"] + i["location"]["width"]):
for Y in range(i["location"]["top"], i["location"]["top"] + i["location"]["height"]):
Used[X, Y] = 1
# with open(r"D:/1.txt", "w") as Wrt:
# for p in Used:
# for q in p:
# Wrt.write(str(q) + ",")
# Wrt.write("\n")
#从一处文字开始入手
# print("文字坐标:",Tx, Ty)
# dot(Tx, Ty, (0, 0, 255))
Points = sorted(Points, key=lambda x:((x[0] - Tx) ** 2 + (x[1] - Ty) ** 2) + 10 ** 8 * checktext(T, x[0], x[1]))
#print(Points)
# for i in Points:
# if checktext(T, i[0], i[1]) != True:
# dot(i[0], i[1], (255, 0, 0))
Nowx, Nowy = Points[0][0], Points[0][1]
# Startx, Starty = Nowx, Nowy
# print(Nowx, Nowy)
# dot(Nowx, Nowy, (0, 255, 0))
# dot(Points[10][0], Points[10][1], (0, 255, 0))
# Q.save("new.bmp")
# Q.show()
# dx = abs(Points[1][0] - Points[0][0])
# dy = abs(Points[1][1] - Points[0][1])
Linex = []
Liney = []
# print(dx, dy)
# while Points.count((Nowx, Nowy)):
# Used[Nowx, Nowy] = 1
# Linex.append(Nowx)
# Liney.append(Nowy)
# Nowx += dx
# Nowy += dy
# Linex.append(Nowx)
# Liney.append(Nowy)
# print(Linex, Liney)
# Lines.append([Linex, Liney])
# Linex.clear()
# Liney.clear()
while True:
Used[Nowx, Nowy] = 1
k = Findnear((Nowx, Nowy))
if len(k) == 0:
break
dx = k[0][0] - Nowx
dy = k[0][1] - Nowy
# print("---------------", dx, dy)
Pnow = k[0]
Used[Pnow[0], Pnow[1]] = 1
Linex.append(Pnow[0])
Liney.append(Pnow[1])
# print(Findnear((367,79), 3))
# sleep(3)
while True:
flag = False
# if (Used[Pnow[0] + dx, Pnow[1] + dy] != 1) & (Points.count((Pnow[0] - dx, Pnow[1] - dy)) != 0):
# Used[Pnow[0] + dx, Pnow[1] + dy] = 1
# Q.putpixel((Pnow[0] + dx, Pnow[1] + dy), Col[0])
# Linex.append(Pnow[0] + dx)
# Liney.append(Pnow[1] + dy)
# Pnow = (Pnow[0] + dx, Pnow[1] + dy)
# continue
for tmp in Findnear((Pnow[0], Pnow[1])):
Tan1 = (tmp[0] - Pnow[0]) * dy - (tmp[1] - Pnow[1]) * dx
Tan2 = (1 + (tmp[0] - Pnow[0]) * dx)
if Tan1 * Tan2 > 0:
F1 = (Tan1 <= Tan2 * math.sqrt(1/3))
else:
F1 = (Tan1 * -1 <= Tan2 * math.sqrt(1/3))
if F1 and (Used[tmp[0], tmp[1]] == 0):
Used[tmp[0], tmp[1]] = 1
Q.putpixel((tmp[0], tmp[1]), Col[0])
Linex.append(tmp[0])
Liney.append(tmp[1])
# print(tmp)
Pnow = tmp
flag = True
break
# print("break1!")
if flag == False:
break
Nowx, Nowy = Linex[-1], Liney[-1]
Lines.append((Linex, Liney))
print(Lines)
Linex.clear()
Liney.clear()
with open("D:/化学俱乐部项目/Lines.txt", "w") as f:
f.write(str(len(Lines)))
Q.show()