Tesseract.js Javascript OCR文字認識

Canvas から切り抜いた画像でもって、OCRする必要あり、過去にtesseract を使ってサーバー側で処理した結果を応答する仕様のをリリースしたことがあり、今回もそれで行こうと思いましたが、
ちょっと調べたところ、何と、tesseract が Javascript で実行できるようになって、早速、利用してみました。

ここで教えて頂く : https://qiita.com/furunfuru/items/0ecf0a21273ae93bc060

< コード例 >


<script src='https://cdn.rawgit.com/naptha/tesseract.js/0.2.0/dist/tesseract.js'></script>


       // @@ 文字認識ボタンを押した時 @@ //
        $("#execocr").on("click", function (e) {

          //var img = $("#RecCanvas").toDataURL();
          // var img = document.getElementById("RecCanvas").toDataURL();
          var img = document.getElementById("RecCanvas").toDataURL("image/jpeg");

          Tesseract.recognize(img, {lang: "eng"}).then(function (result) {
            //const a = document.querySelector("#test");
            console.log(result);
            $("#ocrres").val(result.text);
          });
         });

< 対象画像 結果例 >

PHP GD 画像切り抜き

< コード例 >


<?php

/**
 * GD 画像 切り抜き
 * argv : 1:元ファイル名, 2:生成ファイル名, 3: 左上X座標, 4: 左上Y座標, 5:幅, 6:高さ  
 */
 
// 引数取得 //
$srcfnm = $argv[1];
$newfnm = $argv[2];
$sx = $argv[3];
$sy = $argv[4];
$w = $argv[5];
$h = $argv[6];

// 元画像サイズ取得 //
list($src_width, $src_height, $type) = getimagesize($srcfnm);

// 対象イメージ格納 //
switch ($type) {
  case IMAGETYPE_JPEG:    // 2
    $srcimg = imagecreatefromjpeg($srcfnm);
    break;
  case IMAGETYPE_PNG:     // 3
    $srcimg = imagecreatefrompng($srcfnm);
    break;
  case IMAGETYPE_GIF:     // 1
    $srcimg = imagecreatefromgif($srcfnm);
    break;
}

// 矩形指定
$rect = array();
$rect['x'] = $sx;
$rect['y'] = $sy;
$rect['width'] = $w;
$rect['height'] = $h;

// 画像を切り抜き
//$im_in = $func_create($srcfnm);
$im_out = imagecrop($srcimg, $rect);

// 結果ファイルに出力 //
$filepath = pathinfo($newfnm);
$ext = mb_strtolower($filepath['extension']);
$res = 1;
try {
  if ($ext === "jpg" || $ext === "jpeg") {
    imagejpeg($im_out, $newfnm, 100);
  }
  else if ($ext === "png") {
    imagepng($im_out, $newfnm, 9);
  }
  else if ($ext === "gif") {
    imagegif($im_out, $newfnm, 100);
  }
}
catch (Exception $ex) {
  $res = 0;
}

// 解放 //
imagedestroy($srcimg);
imagedestroy($im_out);

// 連想配列に格納 //
$responce = [];
$responce["Result"] = $res;

// JSONに変換して結果出力 //
echo json_encode($responce);


?>


コマンドラインで バーコード画像認識 ZBarImg

必要に迫られ、画像ファイルからのバーコード認識ライブラリを探してました。

アプリケーションがJavaでWEBなので、AndroidでないJavaSE の API がふさわしいかと思い、

Zxing を調べてましたが、日本語情報少なく、StaackOverflowの投稿も、Android + QRコードが主、JavaのImageI/Oの記述がややこしく、Java8でエラー多発、未解決のとらうまもあり、

Zxing : https://github.com/zxing/zxing

ImageMagick のようにコマンド1行で目的達成したいので、さらに調べた結果、

ずばりなの見つけて、早速、組み込みました。

ZBarImg で出来ました。

ZBarImg 本家Home : http://zbar.sourceforge.net/

< 利用例 >

オプションなしで EAN13 が読めました。

< Windows >

c:\ZBar\bin>zbarimg R:\#ZBarImgTest\1.png
EAN-13:2400014821369
scanned 1 barcode symbols from 1 images

c:\ZBar\bin>zbarimg R:\#ZBarImgTest\2.png
EAN-13:4582298330770
scanned 1 barcode symbols from 1 images

c:\ZBar\bin>zbarimg R:\#ZBarImgTest\2.jpg
EAN-13:4582298330770
scanned 1 barcode symbols from 1 images


< Linux >

[root@???? zbarimg]# zbarimg 1.png
EAN-13:2400014821369
scanned 1 barcode symbols from 1 images in 0 seconds

[root@???? zbarimg]# zbarimg 1.png
EAN-13:2400014821369
scanned 1 barcode symbols from 1 images in 0 seconds

[root@???? zbarimg]# zbarimg 2.png
EAN-13:4582298330770
scanned 1 barcode symbols from 1 images in 0 seconds

[root@???? zbarimg]# zbarimg 2.jpg
EAN-13:4582298330770
scanned 1 barcode symbols from 1 images in 0 seconds

< 対象画像 >

Cancvsで切り抜き => Base64にエンコードしてアップロード => サーバーで保存

< コード例 >

JavaScript


        // @@ バーコード認識ボタンを押した時 @@ //
        $("#execbarcd").on("click", function (e) {

          // 切り抜き画像 //
          var canvasData = $("#RecCanvas").get(0).toDataURL("");

          // 不要な情報を取り除く
          canvasData = canvasData.replace(/^data:image\/png;base64,/, "");

          var data = {};
          data.file = canvasData;

          // アップロード //
          $.ajax({
            url: 'BarcodeRecog${LW}',
            type: 'POST',
            data: data,
            dataType: 'text',
            success: function (txt) {
              simpleDialog2($("#alertdialog"), "Result", txt, "Close");
              $("#ocrres").val(txt);
            },
            error(jqXHR, textStatus, errorThrown) {
              simpleDialog2($("#alertdialog"), "ERROR", textStatus, "Close");
            },

          });

        });

Javaサーブレット


    String b64txt = request.getParameter("file");

    StringBuffer buf = new StringBuffer();
    try {

      // 時刻文字列 //
      String nowTMSeqStr
              = DateFormatUtils.format(new Date(), "yyyyMMdd_HHmmssSSS");

      // 画像ファイルを保存 //
      byte[] decode = Base64.getDecoder().decode(b64txt);
      String fnm = fileLocationPath + nowTMSeqStr + ".jpg";
      Path path = Paths.get(fnm);
      Files.write(path, decode);
      
      // zbarimgでバーコード取得 //
      String cmd = "c:\\ZBar\\bin\\zbarimg " + fnm;      
      System.out.println(cmd);
      RuntimeExec RE = new RuntimeExec(cmd, 500);
      RE.exec();
      
      // 別クラスにあるRuntimeexecで実行 //
      String restxt = RE.getRestxt();
      String resjan = restxt.substring(restxt.indexOf(":") + 1);
      buf.append(resjan);

    }
    catch (Exception e) {
      e.printStackTrace();
      buf.append(this.FAIL_MESSAGE);
    }

MySQL || で SELECT列の連結

他のデータベースからの移行で、MySQLのSELECT列連結で || が使えないものかと思い、調べてると方法がわかりました。

sql_mode に、PIPES_AS_CONCAT を加えると出来ます。

[ my.cnf 例 ]

sql_mode='NO_ENGINE_SUBSTITUTION,PIPES_AS_CONCAT'

[ SELECT結果例 ]

mysql> select concat(host,user,plugin) from mysql.user where user = 'root' and host = 'localhost';
+------------------------------------+
| concat(host,user,plugin)           |
+------------------------------------+
| localhostrootmysql_native_password |
+------------------------------------+
1 row in set (0.00 sec)

mysql> select host || user || plugin from mysql.user where user = 'root' and host = 'localhost';
+------------------------------------+
| host || user || plugin             |
+------------------------------------+
| localhostrootmysql_native_password |
+------------------------------------+
1 row in set (0.00 sec)

ここで教えていただきました : http://proengineer.internous.co.jp/content/columnfeature/6836#section200

三島由紀夫 : 嘘

精神分析を待つまでもなく、人間のつく嘘のうちで、「一度も嘘をついたことがない」といふのは、おそらく最大の嘘である。

PHP GD 画像ファイル合成

[ コード例 ]


<?php

/**
 * GD 合成位置指定画像ファイル合成 
 * argv : 1:ファイル名A(背景), 2:ファイル名B(パネル), 3:生成ファイル名, 
 *        4:合成位置 (N, NE, E, SE, S, SW, W, NW, C), 5:パッディング (オプション) 
 */

// 引数取得 //
$fnm_a = $argv[1];
$fnm_b = $argv[2];
$fnm_new = $argv[3];
$mrglocation = $argv[4];
$PADDING = isset($argv[5]) ? $argv[5] : 12;   // 指定がない場合は12ピクセル

// Linux 引数の" が認識されてない対策 //
$fnm_a = str_replace("^", " ", $fnm_a);
$fnm_b = str_replace("^", " ", $fnm_b);
$fnm_new = str_replace("^", " ", $fnm_new);

// A, B画像サイズ, 画像タイプ取得 //
list($a_width, $a_height, $type_a) = getimagesize($fnm_a);
list($b_width, $b_height, $type_b) = getimagesize($fnm_b);

// 対象イメージ格納 //
switch ($type_a) {
  case IMAGETYPE_JPEG:    // 2
    $image_a = imagecreatefromjpeg($fnm_a);
    break;
  case IMAGETYPE_PNG:     // 3
    $image_a = imagecreatefrompng($fnm_a);
    break;
  case IMAGETYPE_GIF:     // 1
    $image_a = imagecreatefromgif($fnm_a);
    break;
}
switch ($type_b) {
  case IMAGETYPE_JPEG:    // 2
    $image_b = imagecreatefromjpeg($fnm_b);
    break;
  case IMAGETYPE_PNG:     // 3
    $image_b = imagecreatefrompng($fnm_b);
    break;
  case IMAGETYPE_GIF:     // 1
    $image_b = imagecreatefromgif($fnm_b);
    break;
}

// コピー先の画像,コピー元の画像,コピー先のx座標,コピー先のy座標,コピー元のx座標,コピー元のy座標,コピー元の幅,コピー元の高さ //
// 合成する //
switch ($mrglocation) {
  case "NW":   // 左上
    imagecopy($image_a, $image_b, $PADDING, $PADDING, 0, 0, $b_width, $b_height);
    break;
  case "NE":   // 右上
    imagecopy($image_a, $image_b, $a_width - $b_width - $PADDING, $PADDING, 0, 0, $b_width, $b_height);
    break;
  case "SE":   // 右下
    imagecopy($image_a, $image_b, $a_width - $b_width - $PADDING, $a_height - $b_height - $PADDING, 0, 0, $b_width, $b_height);
    break;
  case "SW":   // 左下
    imagecopy($image_a, $image_b, 12, $a_height - $b_height - $PADDING, 0, 0, $b_width, $b_height);
    break;

  case "N":    // 上中央
    imagecopy($image_a, $image_b, $a_width / 2 - $b_width / 2, $PADDING, 0, 0, $b_width, $b_height);
    break;
  case "S":    // 下中央
    imagecopy($image_a, $image_b, $a_width / 2 - $b_width / 2, $a_height - $b_height - $PADDING, 0, 0, $b_width, $b_height);
    break;
  case "E":    // 右中央
    imagecopy($image_a, $image_b, $a_width - $b_width - $PADDING, $a_height / 2 - $PADDING / 2, 0, 0, $b_width, $b_height);
    break;
  case "W":    // 左中央
    imagecopy($image_a, $image_b, $PADDING, $a_height / 2 - $PADDING / 2, 0, 0, $b_width, $b_height);
    break;
  case "C":    // 中央中央
    imagecopy($image_a, $image_b, $a_width / 2 - $b_width / 2, $a_height / 2 - $b_height / 2, 0, 0, $b_width, $b_height);
    break;
  }


// 結果ファイルに出力 //
$filepath = pathinfo($fnm_new);
$ext = mb_strtolower($filepath['extension']);
$res = 1;
try {
  if ($ext === "jpg" || $ext === "jpeg") {
    imagejpeg($image_a, $fnm_new, 100);
  }
  else if ($ext === "png") {
    imagepng($image_a, $fnm_new, 9);
  }
  else if ($ext === "gif") {
    imagegif($$image_a, $fnm_new, 100);
  }
}
catch (Exception $ex) {
  $res = 0;
}

// 解放 //
imagedestroy($image_a);
imagedestroy($image_b);

// 連想配列に格納 //
$responce = [];
$responce["Result"] = $res;

// JSONに変換して結果出力 //
//echo json_encode($responce, JSON_PRETTY_PRINT);
echo json_encode($responce);

?>


[ 利用例 ]

Aファイル (背景)

Bファイル (パネル)

合成結果 NE パディング指定あり

合成結果 SE

合成結果 SW

合成結果 NW

合成結果 S