画像認識

 投稿者:しばっち  投稿日:2019年 9月26日(木)20時07分27秒
  今現在注目されている技術でAI(人工知能)技術のひとつ機械学習による画像認識を
十進BASIC上で行います。

画像処理ライブラリーopen cvを使用しました。
https://opencv.org/


今回使用したのはWindows版ビルド済み open cv 3.0.0(2015-06-03) VC++2012 x86版です。
このためVC++2012にてコンパイルしました。

※現在の最新版はopen cv 4.1.1(2019-07-26)です。こちらはwin64(x64)のみです。


ライブラリー同梱のカスケードファイル(学習済みデータ)を使用して人物の正面顔を認識させます。
このカスケードファイルを別のに変更することで認識対象を変更することができます。


              ● 用意するもの

正面顔の人物画像(jpg,png) (自画撮り画像 等)
集合写真でも構いません。
※横向きの顔やアニメのキャラなどは認識できません。


なお、実行時にはopencv_world300.dllが必要です(BASIC.EXEと同じフォルダに入れてください)

集合写真の場合は、誤認識分も含めバッファサイズ(変数 N)を多めにしてください。
カスケードファイルのパスを指定してください。


下記URLからダウンロードしてください。(imagetool.zip)

https://36.gigafile.nu/1125-n8d2d72a2da1c926a4d213cd6f41f8bd3

ダウンロード期限:2019年11月25日(月)
ダウンロードキー:設定していません

※警告
open cvは日本語パスに対応していません。


サンプル画像は十進BASIC上で認識させた実行結果です。
認識した正面顔の座標領域(赤枠)は

219  203  389  373

となりました。

OPTION BASE 0
FILE GETNAME IMAGENAME$,"画像ファイル|*.jpg;*.png"
CALL PICTURELOAD(IMAGENAME$,XSIZE,YSIZE)
LET CASCADEFILENAME$="haarcascade_frontalface_default.xml" !'カスケードファイル(学習済みデータ) ※絶対パスか画像と同じフォルダ
LET N=100 !'バッファサイズ(誤認識分を含む100人分)
DIM XS(N),YS(N),XE(N),YE(N)
CALL IMAGEDETECTION(IMAGENAME$,CASCADEFILENAME$,N,XS,YS,XE,YE)
SET LINE WIDTH 4
FOR I=0 TO N-1
   CALL BOX(XS(I),YS(I),XE(I),YE(I),255,0,0)
   !'CALL ELLIPSE((XS(I)+XE(I))/2,(YS(I)+YE(I))/2,(XE(I)-XS(I))/2,(YE(I)-YS(I))/2,0,255,0)
   PRINT XS(I);YS(I);XE(I);YE(I)
NEXT I
END

EXTERNAL SUB IMAGEDETECTION(FILENAME$,CASCADEFIENAME$,N,XS(),YS(),XE(),YE())
OPTION CHARACTER BYTE
LET X0$=REPEAT$(CHR$(0),8*N)
LET X1$=REPEAT$(CHR$(0),8*N)
LET Y0$=REPEAT$(CHR$(0),8*N)
LET Y1$=REPEAT$(CHR$(0),8*N)
LET NUM=IMAGEDETECTION_(FILENAME$,CASCADEFIENAME$,N,X0$,Y0$,X1$,Y1$)
IF NUM=-1 THEN
   PRINT "画像ファイルをロードできません"
   STOP
ELSEIF NUM=-2 THEN
   PRINT "カスケードファイルをロードできません"
   STOP
END IF
IF N>NUM THEN
   FOR I=0 TO NUM-1
      LET XS(I)=UNPACKDBL(X0$(8*I+1:8*I+8))
      LET XE(I)=UNPACKDBL(X1$(8*I+1:8*I+8))
      LET YS(I)=UNPACKDBL(Y0$(8*I+1:8*I+8))
      LET YE(I)=UNPACKDBL(Y1$(8*I+1:8*I+8))
   NEXT I
ELSE
   PRINT "バッファ不足です"
END IF
LET N=NUM
!'
FUNCTION IMAGEDETECTION_(FILENAME$,CASCADEFIENAME$,NUM,X0$,Y0$,X1$,Y1$)
   ASSIGN ".\DLL\imagedetection.dll","imagedetection"
END FUNCTION
END SUB

EXTERNAL SUB PICTURELOAD(N$,XSIZE,YSIZE)
CLEAR
SET COLOR MODE "NATIVE"
SET POINT STYLE 1
IF N$="" THEN STOP
GLOAD N$
LET XSIZE=PIXELX(1)+1
LET YSIZE=PIXELY(1)+1
SET BITMAP SIZE XSIZE,YSIZE
SET WINDOW 0,XSIZE-1,YSIZE-1,0
END SUB

EXTERNAL SUB BOX(XS,YS,XE,YE,R,G,B)
SET COLOR COLORINDEX(R/255,G/255,B/255)
PLOT LINES:XS,YS;XE,YS
PLOT LINES:XE,YS;XE,YE
PLOT LINES:XE,YE;XS,YE
PLOT LINES:XS,YE;XS,YS
END SUB

EXTERNAL  SUB ELLIPSE(X,Y,XR,YR,R,G,B)
OPTION ANGLE DEGREES
SET COLOR COLORINDEX(R/255,G/255,B/255)
PLOT LINES
FOR T=0 TO 360
   LET XX=X+XR*COS(T)
   LET YY=Y+YR*SIN(T)
   PLOT LINES:XX,YY;
NEXT T
PLOT LINES
END SUB

--------------------------------------------------------------------------------------
                                    imagedetection.cpp



#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/objdetect/objdetect.hpp>
#include <opencv2/highgui/highgui.hpp>

using namespace cv;
using namespace std;

extern "C"  __declspec(dllexport) int imagedetection(char *imgfile, char *cascadefile,int num,double *x0,double *y0,double *x1,double *y1)
{
    /* 画像のロード */
    Mat image = imread(imgfile, 1);
    if(!image.data) return -1;

    /* 正面顔検出器のロード */
    CascadeClassifier cascade;
    if(!cascade.load(cascadefile)) return -2;

    vector<Rect> faces;
    int i;

    /* 顔検出 */
    cascade.detectMultiScale(image,faces);

    /* 顔領域 */
    if(num>faces.size()) {
        for( i = 0; i < faces.size(); i++ )
        {
            x0[i]=faces[i].x;
            y0[i]=faces[i].y;
            x1[i]=faces[i].x+faces[i].width;
            y1[i]=faces[i].y+faces[i].height;
        }

    }
    return  faces.size();
}
 

戻る