为什么从 SQLite 数据库检索图像失败

问题描述 投票:0回答:1

我正在使用以下代码将图像保存在 SQLite 数据库中:

import sqlite3
import tkinter as tk
from tkinter import filedialog
from tkinter import messagebox
from PIL import Image, ImageTk
import io

# Connect to SQLite database (or create it if it doesn't exist)
conn = sqlite3.connect('employee_vehicle.db')
c = conn.cursor()

# Create table
c.execute('''CREATE TABLE IF NOT EXISTS employee_vehicle
             (id INTEGER PRIMARY KEY,
              registration_no TEXT,
              chassis_no TEXT,
              name TEXT,
              designation TEXT,
              photo BLOB,
              mobile_no TEXT,
              address TEXT,
              gender TEXT)''')
conn.commit()

# Function to insert data into the database
def insert_data(reg_no, ch_no, name, desig, photo, mob_no, addr, gender):
    with conn:
        c.execute("INSERT INTO employee_vehicle (registration_no, chassis_no, name, designation, photo, mobile_no, address, gender) VALUES (?, ?, ?, ?, ?, ?, ?, ?)", 
                  (reg_no, ch_no, name, desig, photo, mob_no, addr, gender))
        conn.commit()

# Function to load photo
def load_photo():
    file_path = filedialog.askopenfilename(filetypes=[("Image files", "*.jpg;*.png")])
    if file_path:
        img = Image.open(file_path)
        img.thumbnail((100, 100))
        img = ImageTk.PhotoImage(img)
        photo_label.config(image=img)
        photo_label.image = img
        with open(file_path, 'rb') as file:
            photo_data.set(file.read())

# Function to submit form
def submit_form():
    reg_no = reg_no_entry.get()
    ch_no = ch_no_entry.get()
    name = name_entry.get()
    desig = desig_entry.get()
    photo = photo_data.get()
    mob_no = mob_no_entry.get()
    addr = addr_entry.get()
    gender = gender_var.get()

    if all([reg_no, ch_no, name, desig, photo, mob_no, addr, gender]):
        insert_data(reg_no, ch_no, name, desig, photo, mob_no, addr, gender)
        messagebox.showinfo("Success", "Data inserted successfully!")
    else:
        messagebox.showerror("Error", "Please fill all fields!")

# GUI setup
root = tk.Tk()
root.title("Employee Vehicle Registration Form")

tk.Label(root, text="Registration No:").grid(row=0, column=0)
reg_no_entry = tk.Entry(root)
reg_no_entry.grid(row=0, column=1)

tk.Label(root, text="Chassis No:").grid(row=1, column=0)
ch_no_entry = tk.Entry(root)
ch_no_entry.grid(row=1, column=1)

tk.Label(root, text="Name:").grid(row=2, column=0)
name_entry = tk.Entry(root)
name_entry.grid(row=2, column=1)

tk.Label(root, text="Designation:").grid(row=3, column=0)
desig_entry = tk.Entry(root)
desig_entry.grid(row=3, column=1)

tk.Label(root, text="Photo:").grid(row=4, column=0)
photo_label = tk.Label(root)
photo_label.grid(row=4, column=1)
photo_data = tk.StringVar()
tk.Button(root, text="Load Photo", command=load_photo).grid(row=4, column=2)

tk.Label(root, text="Mobile No:").grid(row=5, column=0)
mob_no_entry = tk.Entry(root)
mob_no_entry.grid(row=5, column=1)

tk.Label(root, text="Address:").grid(row=6, column=0)
addr_entry = tk.Entry(root)
addr_entry.grid(row=6, column=1)

tk.Label(root, text="Gender:").grid(row=7, column=0)
gender_var = tk.StringVar()
tk.Radiobutton(root, text="Male", variable=gender_var, value="Male").grid(row=7, column=1)
tk.Radiobutton(root, text="Female", variable=gender_var, value="Female").grid(row=7, column=2)

tk.Button(root, text="Submit", command=submit_form).grid(row=8, columnspan=3)

root.mainloop()

# Close the database connection when done
conn.close()
    

我尝试使用以下代码检索照片并将其保存在文件目录中:

import sqlite3
from cryptography.hazmat.primitives import serialization, hashes
from cryptography.hazmat.primitives.asymmetric import padding
from pyzbar.pyzbar import decode
from PIL import Image
from PyQt5.QtWidgets import QApplication, QFileDialog
import sys
import cv2
import numpy as np
import io
import tempfile
import os

def decrypt_data(private_key, encrypted_data):
    try:
        decrypted_data = private_key.decrypt(
            encrypted_data,
            padding.OAEP(
                mgf=padding.MGF1(algorithm=hashes.SHA256()),
                algorithm=hashes.SHA256(),
                label=None
            )
        )
        return decrypted_data.decode()
    except Exception as e:
        print(f"Debug: Error in decrypt_data: {e}")
        raise

def process_qr_code(image_path):
    try:
        img = Image.open(image_path)
        qr_code_data = decode(img)
        
        if qr_code_data:
            qr_text = qr_code_data[0].data.decode()
            try:
                ch_no, encrypted_data_hex = qr_text.split(":")
                encrypted_data = bytes.fromhex(encrypted_data_hex)
            except ValueError:
                print("Invalid QR code data format.")
                print("Employee does not exist. Output: 0")
                return
            
            private_key_path = f"{ch_no}_private.pem"
            
            try:
                with open(private_key_path, "rb") as key_file:
                    private_key = serialization.load_pem_private_key(
                        key_file.read(),
                        password=None
                    )
                
                decrypted_data = decrypt_data(private_key, encrypted_data)
                
                try:
                    name = decrypted_data.split(",")[0].split(":")[1].strip()
                    mobile_no = decrypted_data.split(",")[1].split(":")[1].strip()
                    
                    print(f"Employee QR verified. Name: {name}")
                    
                    # Retrieve and save employee image
                    retrieve_and_save_image(name)
                    
                    # Capture and recognize face
                    capture_and_recognize_face(f"{name}_retrieve.jpg")
                
                except Exception as e:
                    print(f"Error parsing decrypted data: {e}")
                    print("Employee does not exist. Output: 0")
                    return

            except Exception as e:
                print(f"Error processing data: {e}")
                print("Employee does not exist. Output: 0")
        else:
            print("No QR code found in the image.")
            print("Employee does not exist. Output: 0")
    except Exception as e:
        print(f"Error processing QR code: {e}")
        print("Employee does not exist. Output: 0")

def retrieve_and_save_image(name):
    try:
        conn = sqlite3.connect('employee_vehicle.db')
        c = conn.cursor()
        
        c.execute("SELECT photo FROM employee_vehicle WHERE name = ?", (name,))
        result = c.fetchone()
        
        if result and result[0]:
            photo_blob = result[0]
            
            # Ensure photo_blob is in bytes
            if isinstance(photo_blob, str):
                photo_blob = photo_blob.encode('latin1')  # Convert if needed
            
            # Create the directory if it doesn't exist
            current_dir = os.getcwd()
            image_dir = os.path.join(current_dir, 'retrieved_images')
            os.makedirs(image_dir, exist_ok=True)
            
            image_path = os.path.join(image_dir, f"{name}_retrieve.jpg")
            
            # Save the image using PIL
            image = Image.open(io.BytesIO(photo_blob))
            image.save(image_path)
            print(f"Image '{name}' retrieved and saved as '{image_path}'.")
            
            # Try opening the saved image
            try:
                saved_image = Image.open(image_path)
                saved_image.show()
                print("Saved image opened successfully.")
            except Exception as e:
                print(f"Error opening saved image: {e}")
        else:
            print(f"No image found for '{name}'.")
        
        conn.close()
    except Exception as e:
        print(f"Error accessing database: {e}")
       

def capture_and_recognize_face(image_path):
    face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml')
    recognizer = cv2.face.LBPHFaceRecognizer_create()

    # Load the image from file using PIL
    stored_face_image = Image.open(image_path).convert('L')
    stored_face_image = np.array(stored_face_image)

    if stored_face_image is None:
        print(f"Error loading image from file: {image_path}")
        return

    face_image_resized = cv2.resize(stored_face_image, (200, 200))
    recognizer.train([face_image_resized], np.array([0]))

    video_capture = cv2.VideoCapture(0)
    if not video_capture.isOpened():
        print("Unable to access webcam.")
        return
    
    ret, frame = video_capture.read()
    if ret:
        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        faces = face_cascade.detectMultiScale(gray, scaleFactor=1.3, minNeighbors=5)
        
        if len(faces) > 0:
            (x, y, w, h) = faces[0]
            face_image = gray[y:y+h, x:x+w]
            face_image_resized = cv2.resize(face_image, (200, 200))

            label, confidence = recognizer.predict(face_image_resized)
            
            if label == 0 and confidence < 100:
                print("Facial recognition succeeded. Employee verified. Output: 1")
            else:
                print("Facial recognition failed. Output: 0")
        else:
            print("No face found in the captured image.")
            print("Employee does not exist. Output: 0")
    else:
        print("Unable to capture image from webcam.")
    
    video_capture.release()

def upload_image():
    app = QApplication(sys.argv)
    options = QFileDialog.Options()
    file_path, _ = QFileDialog.getOpenFileName(
        None,
        "Select an Image File",
        "",
        "Image Files (*.jpg *.png *.jpeg);;All Files (*)",
        options=options
    )
    
    if file_path:
        print(f"Selected file: {file_path}")
        process_qr_code(file_path)
    else:
        print("No file selected or operation cancelled.")
        print("Employee does not exist. Output: 0")

if __name__ == "__main__":
    upload_image()

它给了我这个错误: 访问数据库时出错:无法识别图像文件 <_io.BytesIO object at 0x000002E247154BD0> 解析解密数据时出错:[Errno 2] 没有这样的文件或目录:'Pawa_retrieve.jpg'

python image sqlite python-imaging-library
1个回答
0
投票

以下是如何从

sqlite
数据库插入和提取图像的最小示例。我使用
bash
脚本和
sqlite3
可执行文件来设置数据库,并以这种方式插入和提取图像。然后,我在第二部分中使用 Python 添加或提取该数据库中的记录。


这是设置和插入/提取图像的

bash

#!/bin/bash
DB_FILE="example.db"

# Discard any previous database file
rm "$DB_FILE" 2> /dev/null

# Create a table of people, with their names and images in the database
sqlite3 "$DB_FILE" <<EOF
CREATE TABLE People(
  id integer primary key autoincrement,
  image BLOB,
  name text
)
EOF

# See the tables present in the database
echo Following tables are present in database:
echo ".tables" | sqlite3 "$DB_FILE"

# See the schema of the database
echo Schema as follows:
echo ".schema" | sqlite3 "$DB_FILE"

# Insert a person
echo Inserting image
echo "INSERT INTO People (image,name) VALUES(readfile('smiley.png'),'smiley');" | sqlite3 "$DB_FILE"

# Display ids of all records present in the table "People"
echo The following records are in the databasae
sqlite3 "$DB_FILE" <<< "SELECT id,name FROM People;"

# Extract one record
echo Extracting image...
echo "SELECT writefile('extracted.png',image) FROM People WHERE name='smiley';" | sqlite3 "$DB_FILE"

这是两张图片:

enter image description hereenter image description here


这是插入/提取图像的Python:

#!/usr/bin/env python3

import sys
import sqlite3
from pathlib import Path
from PIL import Image
from io import BytesIO

DBFILENAME="example.db"

def insertBLOB(image, name):

    # Connect to database and insert image with given name
    with sqlite3.connect(DBFILENAME) as conn:
        cursor = conn.cursor()
        sql = """INSERT INTO People (image, name) VALUES (?, ?)"""
        data_tuple = (image, name)
        cursor.execute(sql, data_tuple)
        conn.commit()

def retrieveBLOB(name):

    # Connect to database and extract image with given name
    with sqlite3.connect(DBFILENAME) as conn:
        cursor = conn.cursor()
        sql = f"""SELECT image FROM People WHERE name = '{name}'"""
        cursor.execute(sql)
        blob = cursor.fetchone()[0]
    return blob

if __name__ == '__main__':

    # Check all required arguments present
    if len(sys.argv) != 4:
        print(f'Usage: {sys.argv[0]} insert|retrieve filename name', file=sys.stderr)
        sys.exit(1)

    # Pick up parameters
    filename = sys.argv[2]
    person   = sys.argv[3]

    if sys.argv[1] == 'insert':
        # Read image from disk, insert into db
        image = Path(filename).read_bytes()
        insertBLOB(image, person)
    else:
        # Retrieve image from db, write to disk
        image = retrieveBLOB(person)

        # If user only ever inserts JPEGs and only ever extracts JPEGs,
        # or, user only ever inserts/extracts PNGs,
        # we could just do the following single line and be finished
        # Path(filename).write_bytes(image)

        # Howvere, if user can put in JPEG and get out a PNG, or vice-versa, we need PIL to convert
        pImage = Image.open(BytesIO(image)).convert('RGB')
        pImage.save(filename)

然后您可以添加这样的图像:

./sqlite.py insert sad.png sad

并提取这样的图像:

./sqlite.py retrieve extracted.png smiley
最新问题
© www.soinside.com 2019 - 2025. All rights reserved.