SE の雑記

SQL Server の情報をメインに Microsoft 製品の勉強内容を日々投稿

SQL Server 2017 の ML サービスから Cognitive Service の Face API を利用してみる

leave a comment

SQL Server 2017 の ML サービスから、外部の REST と連携ができるのかが気になったので、Cognitive Service のCognitive Service の Face API を例にして試してみました。

参考にした情報としては、次のものになります。

Getting Started with Face API in Python Tutorial
Cognitive-Face-Python
Face API – V1.0

最初に実施することとしては「Windows Firewall の設定変更」が必要となります。

Security Considerations for the R Runtime in SQL Server に記載されているのですが、デフォルトの設定では ML サービスに使用しているユーザーは、ネットワーク経由のアクセスが拒否されている状態となっています。

既定のインスタンスでインストールをしている場合は「Block network access for R local user accounts in SQL Server instance MSSQLSERVER」という「送信の規則」で、接続をブロックするための規則が有効な状態となっていますので、この規則を無効化して、ML サービスがネットワーク経由のアクセスが可能な状態としておきます。

この設定を実施しておかないと「WinError 10013」が発生して、REST API へのアクセスを行うことができません。

image

今回は、SQL Server の BLOB データとして格納されているデータを使用したいので、以下のようなクエリで、画像データを varbinary(max) のフィールドに格納しておきます。
今回は Getting Started with Face API in Python Tutorial に記載されている「detection1.jpg」を格納しています。

SET NOCOUNT ON
DROP TABLE IF EXISTS BlobTable
CREATE TABLE BlobTable (Filename nvarchar(255), Data varbinary(max))
Truncate Table BlobTable
GO
 
DECLARE @blob varbinary(max)
 
SELECT @blob = (SELECT * FROM OPENROWSET(BULK N'C:\Scripts\detection1.jpg', SINGLE_BLOB) as tmp)
INSERT INTO BlobTable VALUES('detection1.jpg', @blob)

 

次に、Face API の Python の SDK を ML サービスで利用するようにインストールします。

cd "C:\Program Files\Microsoft SQL Server\MSSQL14.MSSQLSERVER\PYTHON_SERVICES\Scripts"
pip install cognitive_face

 

これで準備が整いましたので、外部スクリプトとして Python を実行します。

「@key」と「@baseurl」は使用する Cognitive Service の適切な情報に置き換えてください。

DECLARE @filename varchar(255) = 'detection1.jpg'

DECLARE @image varbinary(max)
DECLARE @face nvarchar(max)

DECLARE @key varchar(32) = '<API キー>'
DECLARE @baseurl varchar(max) = 'https://southeastasia.api.cognitive.microsoft.com/face/v1.0/' -- 使用する Cognitive Service のリージョンの適切な URL に置き換える

SELECT @image = Data FROM BlobTable WHERE Filename =@filename

execute sp_execute_external_script 
@language = N'Python',
@script = N'
import io
import cognitive_face as CF

CF.Key.set(key)
CF.BaseUrl.set(baseurl)

_f = io.BytesIO(image)

_result = CF.face.detect(_f, attributes="age,smile,gender")

face = str(_result)
print(_result)
', 
@params = N'@key varchar(32), @baseurl varchar(max), @image varbinary(max), @face nvarchar(max) OUTPUT',
@image = @image,
@key = @key,
@baseurl = @baseurl,
@face = @face OUTPUT

SELECT @filename AS filename, * FROM OPENJSON(replace(@face, '''', '"'))
WITH(
faceid uniqueidentifier '$.faceId',
faceAttributes_gender varchar(20) '$.faceAttributes.gender',
faceAttributes_smile float '$.faceAttributes.smile',
faceAttributes_age float '$.faceAttributes.age',
faceRectangle_Top int '$.faceRectangle.top',
faceRectangle_left int '$.faceRectangle.left',
faceRectangle_width int '$.faceRectangle.width',
faceRectangle_height int '$.faceRectangle.height'
)

 

正常に通信が実行できれば以下のような、REST のレスポンスの JSON をパースした結果が取得できます。

image

最初、InputDataSet として、バイナリデータを渡していたのですが、なぜか先頭の 4 バイトしかわたっておらず、OutPutDataSet で結果を返そうとしても NaN となってしまったので、情報の授受は変数経由にしています…。

 

結構適当ではありますが、以下のようなストアドで顔認識した範囲を囲うこともできそうですね。
適当に書いたので、画像内に複数の人物いても一人にしか枠がつきません…。

DECLARE @filename varchar(255) = 'detection1.jpg'

DECLARE @image varbinary(max)
DECLARE @face nvarchar(max)

DECLARE @key varchar(32) = '<API キー>'
DECLARE @baseurl varchar(max) = 'https://southeastasia.api.cognitive.microsoft.com/face/v1.0/' -- 使用する Cognitive Service のリージョンの適切な URL に置き換える


SELECT @image = Data FROM BlobTable WHERE Filename =@filename

execute sp_execute_external_script 
@language = N'Python',
@script = N'
import io
import cognitive_face as CF
import json
from PIL import Image, ImageDraw

CF.Key.set(key)
CF.BaseUrl.set(baseurl)

_f = io.BytesIO(image)

_result = CF.face.detect(_f, attributes="age,smile,gender")

face = str(_result)
print(_result)

if len(_result) != 0:
    jsondata = json.loads(str(_result[0]).replace("''", "\""))

    img = Image.open(_f)
    draw = ImageDraw.Draw(img)
    draw.rectangle((
    (jsondata["faceRectangle"]["left"],
    jsondata["faceRectangle"]["top"]),
    (jsondata["faceRectangle"]["left"] + jsondata["faceRectangle"]["width"], 
    jsondata["faceRectangle"]["top"] + jsondata["faceRectangle"]["height"])))
    img.save(r"c:\scripts\face_detect.png")

face = str(_result)
', 
@params = N'@key varchar(32), @baseurl varchar(max), @image varbinary(max), @face nvarchar(max) OUTPUT',
@image = @image,
@key = @key,
@baseurl = @baseurl,
@face = @face OUTPUT

SELECT @filename AS filename, * FROM OPENJSON(replace(@face, '''', '"'))
WITH(
faceid uniqueidentifier '$.faceId',
faceAttributes_gender varchar(20) '$.faceAttributes.gender',
faceAttributes_smile float '$.faceAttributes.smile',
faceAttributes_age float '$.faceAttributes.age',
faceRectangle_Top int '$.faceRectangle.top',
faceRectangle_left int '$.faceRectangle.left',
faceRectangle_width int '$.faceRectangle.width',
faceRectangle_height int '$.faceRectangle.height'
)

Written by masayuki.ozawa

7月 6th, 2017 at 10:49 pm

Posted in SQL Server

Tagged with ,

Leave a Reply

*