为啥我不能从数据库中保存和检索我的向量(二进制)和特殊字符?
Posted
技术标签:
【中文标题】为啥我不能从数据库中保存和检索我的向量(二进制)和特殊字符?【英文标题】:Why can't I save and retrieve my vector(binary) and special characters from the database?为什么我不能从数据库中保存和检索我的向量(二进制)和特殊字符? 【发布时间】:2021-12-14 10:20:40 【问题描述】:我正在使用 python 模块 'face_recognition' 和 'pickle' 和 DB 'PostgreSQL' 从数据库中保存和检索我的面部矢量,但我遇到了编码问题。
如果未启用 UTF-8 编码,我将无法保存规范字符 '????'到我的数据库。
启用 UTF-8 编码后,我无法从数据库中取回我的对象。
import cv2
import pickle
import face_recognition
import mysql.connector as mysql
conn = mysql.connect(
host = 'localhost',
user = 'root',
passwd = 'superpassword'
)
# Open image
img = face_recognition.load_image_file('test.jpg')
# Get vector
face_vector = face_recognition.face_encodings(img)[0]
cur = conn.cursor(buffered=True)
cur.execute("CREATE DATABASE IF NOT EXISTS test;")
cur.execute("USE test;")
# WITHOUT UTF-8 I GETTING THIS ERROR:
# Error: mysql.connector.errors.DataError: 1366 (22007): Incorrect string value: '\xF0\x9D\x95\xB2' for column `test`.`test`.`bug_char` at row 1
#cur.execute("SET NAMES 'utf8';")
#cur.execute("SET CHARACTER SET utf8;")
cur.execute("CREATE TABLE faces(bug_char VARCHAR(32), vectors BLOB)")
data_insert = ('????', pickle.dumps(face_vector))
cur.execute('INSERT INTO faces(bug_char, vectors) VALUES(%s, %s)', data_insert)
cur.execute("SELECT * FROM faces;")
face_data = cur.fetchall()
for f in face_data:
print(pickle.loads(f[1]))
# AND WITH UTF-8 I GETTING THIS ERROR WHEN I TRY TO GET MY OBJ FROM DB:
'''
Traceback (most recent call last):
File "/home/user/Desktop/parser_steam/image_recognition/test/./test.py", line 203, in <module>
print(pickle.loads(f[1]))
_pickle.UnpicklingError: invalid load key, '?'.
'''
对不起我的英语。
【问题讨论】:
????
是“MATHEMATICAL BOLD FRAKTUR CAPITAL G”,它需要 utf8mb4,而不是 utf8。或者是BINARY
或BLOB
的列。
【参考方案1】:
每个人脸编码都是一个包含 128 个浮点数的列表...以下内容可能很好地解释了为什么会提出您的问题以及该怎么做。
"pickling 是递归的,而不是顺序的。因此,要腌制一个列表,pickle 将开始腌制包含列表,然后腌制第一个元素……深入第一个元素并腌制依赖项和子元素,直到第一个元素序列化。然后移动到列表的下一个元素,依此类推,直到它最终完成列表并完成对封闭列表的序列化。简而言之,除了某些特殊情况外,很难将递归泡菜视为顺序。如果您想以特殊方式加载,最好在转储中使用更智能的模式。
最常见的pickle,它通过一次转储到文件来腌制所有内容——但是您必须一次加载所有内容。但是,如果您打开一个文件句柄并执行多个转储调用(例如,列表的每个元素一个,或者一个选定元素的元组),那么您的加载将反映...您打开文件句柄并执行多个加载调用,直到您拥有所有列表元素并且可以重建列表。然而,选择性地仅加载某些列表元素仍然不容易。为此,您可能必须使用 klepto 之类的包将列表元素存储为 dict(以元素或块的索引作为键),它可以透明地将腌制的 dict 分解为多个文件,并启用轻松加载特定元素。”
(source)
【讨论】:
【参考方案2】:使用BLOB
列而不是TEXT
。
【讨论】:
以上是关于为啥我不能从数据库中保存和检索我的向量(二进制)和特殊字符?的主要内容,如果未能解决你的问题,请参考以下文章
为啥 BotUserData 在我的 Bot Framework 机器人中不能持久化和可检索?