エックスサーバーにOpenCVをインストールして画像処理APIを作るまで
OpenCVをエックスサーバーで動かしたい
エックスサーバーへPythonとOpenCV+falconを導入して、画像処理APIを作ろうと思いました。
OpenCVをエックスサーバーのサーバー上で動かす方法を、自分が探した限りでは、2021/09現在有効なWeb上に正しい情報がないと思います(コマンドラインから動作させる方法は見つかりますが)。そこで、まとめてみました。
まず、pipインストールをできるようにします。この辺でpipは、情報は色々転がっていますが、情報が古く、使えないパターンが多いです。
エックスサーバーではルート権限を持っていないので、普通にインストールすることはできません。解決法は、おおむね仮想環境をインストールして、そこにPythonをインストールのうえ、pipインストールするか、予めインストールされているPythonの仮想環境を使用するかのいずれかです。
ただ、予めインストールされているPythonの仮想環境では、Pythonのバージョンがエックスサーバーであらかじめインストールされているものに固定されるので、よろしくありません。また、ライブラリインストール時にエラーが出ます。
仮想環境をインストールする方法を調べてみたところ、linuxbrewを使うかanacondaを使う方法があるのですが、linuxbrewを使用する方法はlinuxbrewにアップデートが入ったようで、情報が古くなっており、導入できません。
ですので、Anacondaを導入します。
Anacondaダウンロード
以下のリンクより、Linux用インストーラを取得し、ダウンロードします。
https://www.anaconda.com/products/individual
Windowsでアクセスしているからか、ページ上部のダウンロードボタンがWindows用となっています。ページ下部にLinux用のインストーラがありますので、こちらをダウンロードしましょう。
そして、エックスサーバーにFTPやファイル管理パネルでアップロードします。
SSH接続
エックスサーバーにSSH接続します。TeraTermなどクライアントソフトをインストールし、以下のエックスサーバーのマニュアルに従って接続しましょう。
https://www.xserver.ne.jp/manual/man_server_ssh.php
Anacondaインストール
アップロードした.shファイルをshコマンドで実行すればよいです。
途中色々聞かれますが、言われた通り突き進みましょう。
以下はENTERを押すと規約が出てくるので、進める。
[xs******@sv12013 ~]$ sh Anaconda3-2021.05-Linux-x86_64.sh
Welcome to Anaconda3 2021.05
In order to continue the installation process, please review the license
agreement.
Please, press ENTER to continue
>>>
以下はyesと応答。
Last updated April 5, 2021
Do you accept the license terms? [yes|no]
[no] >>>
Please answer 'yes' or 'no':'
>>> yes
以下はENTERで進める。
Anaconda3 will now be installed into this location:
/home/xs******/anaconda3
- Press ENTER to confirm the location
- Press CTRL-C to abort the installation
- Or specify a different location below
インストールが終わると、以下のようなメッセージが出力される。
Thank you for installing Anaconda3!
===========================================================================
Working with Python and Jupyter notebooks is a breeze with PyCharm Pro,
designed to be used with Anaconda. Download now and have the best data
tools at your fingertips.
PyCharm Pro for Anaconda is available at: https://www.anaconda.com/pycharm
condaコマンド実行
インストールが終わったのでcondaコマンドが使える、と思って打ってみると、あれ?
[xs******@sv12013 ~]$ conda
pyenv: conda: command not found
The `conda' command exists in these Python versions:
anaconda3-2020.11
Note: See 'pyenv help global' for tips on allowing both
python2 and python3 to be found.
どうも、既にpyenvとかを導入していると、Anacondaと競合してしまうらしいです。
Anacondaを優先(pyenvを使わない)するために.bashrcに以下の内容を追記します。(******はサーバー番号)
export PATH="/home/xs******/anaconda3/bin/:$PATH"
設定を有効にするために、以下をコマンド入力。
[xs******@sv12013 ~]$ source .bashrc
これでcondaコマンドが有効になりました。
conda環境の起動
condaの環境をアクティベートして、conda環境に切り替えます。「CommandNotFoundError」となった場合は、conda initしてターミナルを再起動すると治るはずです。
[xs******@sv12013 ~]$ conda init
[xs******@sv12013 ~]$ conda activate
(base) [xs******@sv12013 ~]$
ちなみに、conda環境から抜けるときは、「conda deactivate」します。
(base) [xs******@sv12013 ~]$ conda deactivate
pipインストール
conda環境でpipが使えるようになったと思いますので、pipで必要なopencv-python、falconをインストールしていきます。
opencv-pythonのインストール
コマンド「pip install opencv-python」を投入し、インストール完了後「python」コマンドでpythonを対話モードで起動。「import cv2」してエラーとならないことを確認しましょう。
完了したら「exit()」で抜けます。
(base) [xs******@sv12013 ~]$ pip install opencv-python
Collecting opencv-python
Downloading opencv_python-4.5.3.56-cp38-cp38-manylinux2014_x86_64.whl (49.9 MB)
|????????????????????????????????| 49.9 MB 482 kB/s
Requirement already satisfied: numpy>=1.17.3 in ./anaconda3/lib/python3.8/site-packages (from opencv-python) (1.20.1)
Installing collected packages: opencv-python
Successfully installed opencv-python-4.5.3.56
(base) [xs******@sv12013 ~]$ python
Python 3.8.8 (default, Apr 13 2021, 19:58:26)
[GCC 7.3.0] :: Anaconda, Inc. on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import cv2
>>> exit()
falconの導入
opencv-pythonと同様。falcon-multipartもインストールする。
(base) [xs******@sv12013 ~]$ pip install falcon
Collecting falcon
Downloading falcon-3.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (9.9 MB)
|????????????????????????????????| 9.9 MB 7.8 MB/s
Installing collected packages: falcon
Successfully installed falcon-3.0.1
(base) [xs******@sv12013 ~]$ python
Python 3.8.8 (default, Apr 13 2021, 19:58:26)
[GCC 7.3.0] :: Anaconda, Inc. on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import falcon
>>> exit()
(base) [xs*******@sv12013 ~]$ pip install falcon_multipart
Collecting falcon_multipart
Using cached falcon_multipart-0.2.0-py3-none-any.whl (5.2 kB)
Requirement already satisfied: falcon>=0.3 in ./anaconda3/lib/python3.8/site-packages (from falcon_multipart) (3.0.1)
Installing collected packages: falcon-multipart
Successfully installed falcon-multipart-0.2.0
numpyのアップデート
後の話ですが、「import cv2」したところ、先へ進みませんでした。色々試行錯誤したところ依存ライブラリのnumpyのアップデートが必要だったので、ここで実行しておきます。
pip install -U numpy
Requirement already satisfied: numpy in ./anaconda3/lib/python3.8/site-packages (1.20.1)
Collecting numpy
Using cached numpy-1.21.2-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl (15.8 MB)
Installing collected packages: numpy
Attempting uninstall: numpy
Found existing installation: numpy 1.20.1
Uninstalling numpy-1.20.1:
Successfully uninstalled numpy-1.20.1
Successfully installed numpy-1.21.2
APIを作る
例として、受信した画像をcvcvtColorでグレースケール化して応答する単純なAPIを開発します。
以下の3つのファイルを作成し、同一フォルダに置きましょう。
- __init__.py(中身はブランク)
- index.cgi
- opencv.py
- .htaccess
index.cgiの内容
#! /home/xs******/anaconda3/bin/python3
import os
os.environ['OPENBLAS_NUM_THREADS'] = "1"
from wsgiref.handlers import CGIHandler
from opencv import app
CGIHandler().run(app)
1行目の「#! /home/xs******/anaconda3/bin/python3」はanacondaのpythonの位置を示します。場所が怪しいときは、condaをアクティベートした状態の端末(TeraTerm)で「which python3」とコマンド入力すると、パスが出てきます。頭の「~」は「/home/{サーバーID}」で読み替えましょう。
(base) [xs******@sv12013 ~]$ which python3
~/anaconda3/bin/python3
基本はfalconでAPIを構築するフォーマット通りですが、「os.environ['OPENBLAS_NUM_THREADS’] = “1"」という記述を加えています。opencv-pythonが依存しているnumpyはマルチスレッドで計算できるのですが、エックスサーバー環境ではマルチスレッドでは動かないので、1を指定してシングルスレッドで処理するよう制約しています。
opencv.pyの内容
POSTで画像ファイルを受け付け、cvcvtColorしてバイトデータを返します。
import sys
import traceback
try:
import ctypes
#ctypes.cdll.LoadLibrary('/lib64/libGLdispatch.so.0')
#ctypes.cdll.LoadLibrary('/lib64/libGLX.so.0')
#ctypes.cdll.LoadLibrary('/lib64/libGL.so.1')
import cv2
import falcon
from falcon_multipart.middleware import MultipartMiddleware
import tempfile
from io import BytesIO
except Exception as e:
#例外が発生した場合
exception_info = traceback.format_exc()
with open("debug.txt", mode='a') as f:
f.write(exception_info)
class Imageproc(object):
def __init__(self): #初期化: インスタンス作成時に自動的に呼ばれる
self.test = []
def on_get(self, req, resp):
resp.status = falcon.HTTP_200
resp.content_type = 'text/plain'
resp.body = "Please use POST request!"
def on_post(self, req, resp):
try:
image_data = req.get_param('file').file.read() #POSTリクエストから画像取り出し。
#テンポラリファイルに画像を書き込む。
fp = tempfile.NamedTemporaryFile()
fp.write(image_data)
#opencvの形式で画像読み込み
cv_img = cv2.imread(fp.name)
#グレースケール変換
gray = cv2.cvtColor(cv_img, cv2.COLOR_BGR2GRAY)
#Jpeg形式のバイナリデータに変換
is_success, buffer = cv2.imencode(".jpg", gray)
io_buf = BytesIO(buffer)
#レスポンス
resp.status = falcon.HTTP_200
resp.content_type = 'application/octet-stream'
resp.data = io_buf.getvalue()
except:
#例外が発生した場合
exception_info = traceback.format_exc()
with open("debug.txt", mode='a') as f:
f.write(exception_info)
class CORSMiddleware:
def process_request(self, req, resp):
resp.set_header('Access-Control-Allow-Origin', '*')
try:
app = falcon.App(middleware=[CORSMiddleware(), MultipartMiddleware()])
app.add_route("/", Imageproc())
except Exception as e:
#例外が発生した場合
exception_info = traceback.format_exc()
with open("debug.txt", mode='a') as f:
f.write(exception_info)
if __name__ == "__main__":
from wsgiref import simple_server
httpd = simple_server.make_server("127.0.0.1", 80, app)
httpd.serve_forever()
.htaccess
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ /test/opencv_api/index.cgi/$1 [QSA,L]
以上でAPIが完成しました。
テスト
何か画像ファイルを用意し、curlでリクエスト、受信データを保存してみます。
curl -X POST -F file=@input_test.jpg https://{domain}/test/opencv_api/ -O output_test.jpg
ディスカッション
コメント一覧
まだ、コメントがありません