SE の雑記

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

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

without comments

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