Help us understand the problem. What is going on with this article?

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

More than 3 years have 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との連携処理などを実装していきたいと思います。

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

nyagato_00
Twitterのnyagato_00です. Qiitaの方のアカウントを作りました.主には画像処理・センサ信号処理を大学時代の研究で行っていました。今は組み込みエンジニアからRailsエンジニアにジョブチェンジしました。
iwate-pu
岩手県滝沢市にある公立大学です。Qiitaではソフトウェア情報学部生や出身の人が多いです。
https://www.iwate-pu.ac.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away