サクラエディタで snakecase ⇔ camelcase

以前、Excel VBA で、Python で書いた snake case ⇔ camel case スクリプトで、
Excel 上に入力したものを変換する方法を書いた。
oboe2uran.hatenablog.com

でも、Python が入っていないPC環境では不可能なので他の方法で日常、すぐに使える方法はないかと
探していたら、サクラエディタに JSでマクロ登録する方法を見つけました。
【サクラエディタ】スネーク⇔キャメル変換するマクロ - Qiita
ありがたく使わせて頂き、御礼申し上げます。

以下のJSソースを用意します。(上記、掲載をそのままコピーさせていただきます。)
snakeToCamel.js

function converter(match, offset, string){
   var inp = match;
   if (/^[A-Z0-9]+$/.test(inp)){
      return inp.toLowerCase();
   }
  //スネークケースかどうか?アンダースコアがあるか?
   if (/_/.test(inp)){
      //スネーク→キャメル
      //全て小文字に
      inp = inp.toLowerCase();
      //区切り文字の後を大文字に
      inp = inp.replace(/(_|^)(.)/g, snakeToCamelConv);
      //先頭を小文字に
      inp = inp.charAt(0).toLowerCase() + inp.slice(1);
   }else{
      //キャメル→スネーク
      //大文字の前に「アンダースコア」を追加
      inp = inp.replace(/([A-Z])/g, camelToSnakeConv);
      //全て大文字に
      inp = inp.toUpperCase();
   }
   return inp;
}

function snakeToCamelConv(match, p1, p2, offset, string){
   return p2.toUpperCase();
}

function camelToSnakeConv(match, p1, offset, string){
   return '_' + p1;
}

//(INPUT)選択範囲を取得
var str = Editor.GetSelectedString(0);
//(PROCESS)スネークケース⇔キャメルケース
str = str.replace(/(\w+)/g, converter);
//(OUT)編集したテキストを設定
Editor.InsText(str);

サクラエディタの「共通設定」のマクロタブを開きます。
マクロ一覧の箇所が、マクロを読み込む場所になります。
f:id:posturan:20210218231053j:plain
用意したJSソースのフォルダをここで指定します。
デフォルトは、ユーザープロファイルの AppData¥Roaming¥sakura になっていると思います。
適当に macro とかフォルダを作ってそれを指定します。
「参照」ボタンで指定します。
f:id:posturan:20210218231124j:plain
下のファイルのプルダウンでマクロを書いたJSソースを指定します。
f:id:posturan:20210218231145j:plain

適当に名前を付けて「設定」を実行します。
f:id:posturan:20210218231159j:plain
番号のところに設定されたものが表示されて、OKで、準備完了です。
f:id:posturan:20210218231215j:plain

変換を実行するときは、対象を含むように範囲指定してから、
ツール → 登録済みマクロ で実行します。

f:id:posturan:20210218231230j:plain

Eclipse が起動しない JVM is not suitable for this product

Eclipse Pleiades 2020年版をインストールして起動したら、
JVM is not suitable for this product; Version 11 or grater is required
と表示され起動できなかった。
f:id:posturan:20210213231510j:plain

Java11 以降を前提としており、環境として Java8 で開発したり Java11 で開発したり
することがあり、デフォルトを Java8 のJREの PATH にしているとこのように
起動できない。

eclipse.ini で起動オプションに、JavaVM を指定させる。

-vm
C:/Java/jdk-11.0.2/bin/javaw.exe

のように、Java11 をインストールした場所を追加すると良いのだが、
注意が必要で最後に書いたのではダメで以下のようにする。

  • vmargs の前に書く!
-product
org.eclipse.epp.package.jee.product
--launcher.defaultAction
openFile
--launcher.appendVmargs
-vm
C:/Java/jdk-11.0.2/bin/javaw.exe
-vmargs
-Dosgi.requiredJavaVersion=11
-XX:+UseG1GC
-XX:+UseStringDeduplication
--add-modules=ALL-SYSTEM
-Dosgi.dataAreaRequiresExplicitInit=true
-Xverify:none
-javaagent:dropins/MergeDoc/eclipse/plugins/jp.sourceforge.mergedoc.pleiades/pleiades.jar
-javaagent:lombok.jar

サクラエディタのメニューアイコンが消えた時

サクラエディタを再インストールした時だったか、急にサクラエディタのメニューのアイコンが表示されなくなった。

対処は、、

サクラエディタ常駐してたら、まずは終了して、

%UserProfile%\AppData\Roaming\sakura\

を開き、このフォルダにある sakura.ini ファイルを一度削除する。

Stream の最後を求める

どうしても stream で処理するなら、reduce による集計で求める

サンプル

List<String> list = List.of("A", "B", "C". "D". "E");

String last = list.stream().reduce((a, b) -> b).orElse(null);

last → "E"

stream の先頭なら、reduce((a, b) -> a)

list が空なら、
last → null

Optional の stream() メソッド

未だに Java バージョンが、Java8 のままのプロジェクトが多く、以降のバージョンで追加された
メソッドの恩恵を受ける機会に恵まれず、追加メソッドの存在を忘れてしまってる。

Optional のリストがあった時に、null でないものだけを Stream で処理したい時、

Optional にある public Stream<T> stream() を使う。

これは、Java9 で追加されたメソッド

List<Optional<String>> list = // TODO セット

list.stream().flatMap(Optional::stream).forEach(e->{
    // TODO null でない 文字列 e に対する処理
});

OpenCV 画像認識 detectMultiScale を実行してプロセスが終了しない

Windows環境、Python で、OpenCV で、画像から顔検出
OpenCV: Face Detection using Haar Cascades

顔認識として、以下から取得したカスケードファイル
opencv/data/haarcascades at master · opencv/opencv · GitHub

haarcascade_frontalface_default.xml 正面を向いた顔の認識用カスケードファイル
haarcascade_eye.xml 瞳を認識するカスケードファイル

(他にも、haarcascade_smile.xml など、笑顔の認識用などあるので参考に)

これで、cv2.CascadeClassifier より、
抽出処理 detectMultiScale を実行すると、処理が終わってもプロセスは停止しない。
OpenCVは、opencv-python 4.5.1.48 を使っている。

良い方法が見つからなかったので、並行処理プロセス multiprocessing で実行させる。
サンプル
cascade というフォルダに検出用のカスケードファイルを置き、
検出対象の画像pahと、検出後、検出部分を四角形で囲んだ画像を書込むpathを指定して実行する
クラスを用意して、multiprocessing で実行、
join(timeout=1) で待ち合わせて、.terminate() で終了させる。

# -*- coding: UTF-8 -*-
import cv2
import multiprocessing

class facecatch():
    def __init__(self):
        face_cascade_path = 'cascade/haarcascade_frontalface_default.xml'
        eye_cascade_path = 'cascade/haarcascade_eye.xml'
        self.face_cascade = cv2.CascadeClassifier(face_cascade_path)
        self.eye_cascade = cv2.CascadeClassifier(eye_cascade_path)
    def catch(self, inpath, out):
        src = cv2.imread(inpath)
        src_gray = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY)
        faces = self.face_cascade.detectMultiScale(src_gray)
        count = 0
        for (x, y, w, h) in faces:
            face = src[y: y + h, x: x + w]
            face_gray = src_gray[y: y + h, x: x + w]
            eyes = self.eye_cascade.detectMultiScale(face_gray)
            if len(eyes) == 2:
                count = count + 1
                cv2.rectangle(src, (x, y), (x + w, y + h), (255, 0, 0), 2)
        if count > 0:
            cv2.imwrite(out, src)
        return count

class Worker(multiprocessing.Process):
    def __init__(self):
        super().__init__()
    def setImagePath(self, imgpath, outpath):
        self.imgpath = imgpath
        self.outpath = outpath
    def run(self):
        self.f = facecatch()
        self.cnt = self.f.catch(self.imgpath, self.outpath)
        print('検出 count = %d' % self.cnt)
        return self.cnt
    def getcount(self):
        return self.cnt

if __name__ == '__main__':
    p = Worker()
    p.setImagePath('data/lena.jpg', 'out/result.jpg')
    p.start()
    p.join(timeout=1)
    p.terminate()
    print('finish !')

このサンプルは、顔の輪郭の中で、瞳を認識(瞳を2個検出)しないと、顔として検出したことにしない方法である。

deselect_node.jstree Event

jsTree で選択中のノードを解除する操作は、ctrl キーを押しながら
選択しているノードをマウスクリックする。

このイベントを拾うイベント名は、deselect_node.jstree

よって、 選択が外れた時の処理を記述する場合は、、

$('#tree').jstree({
       // 省略
}).on('deselect_node.jstree', function(e, data){
     // TODO 選択が外れた時の処理
});