Posted at

pythonで画像をDBに登録し、DBから取得する

More than 1 year has passed since last update.


目的

業務にて画像をSQLite3のDBへ登録し保存する機能を実装する必要があり、調査を兼ね実装を行いました。

HTTPサーバーを兼ねたRaspberry PiにUSB接続のWebカメラを接続し、このカメラを外部から制御(画像の撮影)を行い、サーバー内のDBへ保存します。

外部機器(PC、スマートフォン)からサーバーへリクエストをかけたら、任意の画像を取得するなどの機能を実装する必要がありました。

今回は、有線接続したWebカメラから画像を取得し、DBへ保存、保存完了後にDBから画像を取得し、ローカルディレクトリに任意のファイルネームで保存するまでを実装しました。


開発環境


IDE

PyCharm Community Edition


ライブラリ

SQLite3

OpenCv

PyQt5


環境構築

pythonはHomebrewでインストールします。

SQLite3はpythonに標準で入っているので、インストールは不要です。

OpneCvはPyCharmからインストールしました。

Preference->Project Interpreterを開き、+ボタンを押します。

Availabel Packagesが開くので、opencv-pythonを検索し、Install Packageにてインストールしました。

PyQt5はHomebrewでインストールします。

brew install pyqt5


実装


save_db.py

import cv2

import sqlite3
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton
from PyQt5.QtGui import QIcon
from PyQt5.QtCore import pyqtSlot

class App (QWidget):

def __init__(self):
super().__init__()
self.title = 'Sample image to save to DB'
self.left = 10
self.top = 10
self.width = 320
self.height = 240
self.initUI()

def initUI(self):

# ウィンドウのtitleを設定
self.setWindowTitle(self.title)

# ウィンドウサイズを設定
self.setGeometry(self.left, self.top, self.width, self.height)

# ボタンのtitleを設定
buttton = QPushButton('Save Captcha to DB', self)
# ボタンの意味を設定
buttton.setToolTip('This is a button to save the camera Captcha image to DB')
# ボタンの描画位置を設定
buttton.move(80, 70)
# ボタン押下処理を設定
buttton.clicked.connect(self.on_click)

self.show()

def camera_capture(self):
cap = cv2.VideoCapture(0)
count = 0

while count < 10:
count+=1
ret, frame = cap.read()
# デバッグ用:画像表示
#cv2.imshow('camera capture', frame)
cv2.waitKey(1)

if count == 10:
# データベース作成・コネクション作成
db = sqlite3.connect("my.db")
# カーソルをコネクションから作成
cur = db.cursor()
# テーブル作成
try:
cur.execute('''create table images (id string, img blob)''')
except sqlite3.OperationalError:
print
"table images already exists!"

# コネクションを保存(コミット)
db.commit()

# 画像エンコーディング
_, enc = cv2.imencode(".png", frame)

# データを追加
sql = "insert into images values (?, ?)"
cur.execute(sql, ("camera", memoryview(enc)))

# コネクションを保存(コミット)
db.commit()

# データの読み出し
# byteデータの取得
row = cur.execute('SELECT * FROM images').fetchone()
pic = row[1]

# 画像保存
f = open('load2DBforCameraImage.png', 'wb')
f.write(pic)
f.close()
cur.close()
# OpneCvでも画像保存
cv2.imwrite("save.png", frame)

cap.release()
exit()

@pyqtSlot()
def on_click(self):
print('button on click!')
self.camera_capture()

if __name__ == '__main__':
app = QApplication(sys.argv)
ex = App()
sys.exit(app.exec_())



結果

スクリーンショット 2017-09-17 20.29.56.png

中央のボタンを押下すると、画像をVideoCaptchaの画像をDBへ保存し、その後DBから取得しリネームしローカルディレクトに保存します。

ついでに、OpenCvのimwrite()メソッドでも保存を行っています。

現状では、VideoCaptcha()が起動し画像が取得できるまでに、すこし時間がかかるためカウンターを回し、10回カウントしたところで保存処理を行っています。

(C++書いていたときは、特にこんなコトはなかったんですけどね...)

スクリーンショット 2017-09-17 20.38.43.png

上記のとおり、DBから取得しリネームした画像ファイルと、imwrite()メソッドで保存した2つのファイルが出来上がっていることがわかります。


おわりに

CやC++でゴリゴリコードを書いてきて、ここ最近MySQLやPHPなんかをやったりしていました。

今回取り組んだpythonによるSQLite画像の保存処理も、比較的簡単に記述できることがわかりました。

また、PyQt5によるGUIの作成も簡単に行えることがわかりました。

(ImGUIより簡単に書けますね!)

まだ、最終目的の機能は実装出来ていませんので、pythonによるGPIOの制御、javascriptとの連携処理などを実装していきたいと思います。

もっとスマートに記述できる箇所が多々あると思いますので、ツッコミ等頂けましたらと思います。

よろしくお願いします。