指定したフォルダ内の、全ての画像の縦線ノイズを検出し、補正するためのマクロです。
2020/02/15 追記
このプログラムの『高速版』を作成しましたので、こちらもご覧ください!
2020/03/08 追記
横向きスキャン対応版も公開しました!
2020/03/08 追記その2
そもそも縦線の発生しづらいデータを作るためのコツです。実は縦線対策にはこのマクロが一番オススメです!
2020/04/02 追記
縦線ノイズ除去系マクロの最新修正版をまとめました!
マクロコード
//Vertical Noise Correction.txt
//Folder setting
showMessage("Select Open Folder");
openDir = getDirectory("Choose a Directory");
showMessage("Select Save Folder");
saveDir = getDirectory("Choose a Directory");
list = getFileList(openDir);
//JPEG quality
quality=90;
run("Input/Output...", "jpeg=quality gif=-1 file=.csv save_column save_row");
//Segmentation setting
xSegOriginal=20;
ySegOriginal=20;
//BlackZone threshold(L_mean)
TH_kuroBeta=50;
//WhiteLine threshold(s_mean)
TH_whiteLine=20;
//HighIntensity threshold
TH_HighIntensity=20;
//HighCount threshold
TH_countRatio=80;
//correctedValue setting
correctedValue=0;
//operation
x=0;
y=0;
detectedCount=0;
rejectCounter=0;
for (i=0; i<list.length;i++){
open(openDir+list[i]);
saveFlag=0;
correctCount=0;
width=getWidth();
height=getHeight();
run("Specify...", "width=width height=height x=1 y=1");
getStatistics(area,mean_overAll);
//Size of Segment
if(mean_overAll>100){
xSeg=xSegOriginal;
ySeg=ySegOriginal;
}else{
xSeg=xSegOriginal*2;
ySeg=ySegOriginal*2;
}
//value of movement
xStep=floor(xSeg/2);
yStep=floor(ySeg/2);
//progress
print(i+1,"/",list.length,"...Progress=",floor((i+1)/list.length*10000)/100,"%");
depth=bitDepth();
if (depth==8) {
//Segmentation section
for(y=0;y<height-ySeg;y=y+yStep){
for(x=0;x<width-xSeg;x=x+xStep){
run("Specify...", "width=xSeg height=ySeg x=x y=y");
getStatistics(area,L_mean);
//recognize kuroBeta
if(L_mean<TH_kuroBeta){
a=x+5;
b=y;
//small rectangle ROI scan
for(ii=1;ii<xSeg-9;ii++){
b=y;
run("Specify...", "width=1 height=ySeg x=a y=b");
getStatistics(area,s_mean);
//vertical direction scan on detected whiteLine
if(s_mean>TH_whiteLine){
count=0;
for(jj=1;jj<ySeg+1;jj++){
pixel_intensity=getPixel(a,b);
//count HighIntensity
if(pixel_intensity>TH_HighIntensity){
count++;
b++;
}
}
//Noise Correction
if(count>ySeg*TH_countRatio/100){
correctCount++;
print("Noise Correction!!",correctCount);
saveFlag=1;
b=y;
for(iii=1;iii<ySeg+1;iii++){
setPixel(a,b,correctedValue);
b=b+1;
}
}
}
a=a+1;
}
}
}
}
}else{
rejectCounter++;
print("...Color Image!");
}
if(saveFlag==1){
name=getTitle();
dotIndex=lastIndexOf(name,".");
title=substring(name,0,dotIndex);
newname = title+".jpg";
rename(newname);
saveAs("Jpeg", saveDir+newname);
detectedCount++;
}
close();
}
print("DetectedCounts=",detectedCount);
print("oshimai");
アルゴリズムの概要
①作業対象となるOpen Folderと保存先のSave Folderを設定。
②画像を順番に開き、小さなセグメントを移動させ、平均値を調べることで黒ベタ塗りの部分を探す。
③黒ベタがみつかれば、セグメントの中を縦細長のROI走査で平均値チェックして、線状の高信号(白線)を探す。
④白線を見つけたら、その白線の信号値を上から1ピクセルずつ調べる。
⑤その白線上で、高信号ピクセルが占める割合が80%(デフォルト値)以上だったら、縦線ノイズと認識。
⑥縦線ノイズに該当する縦細長ROI部分をcorrectedValue(デフォルト値=0)で埋める。
⑦すべてのセグメント・画像でこれを繰り返す。
⑧検出・修正したページのみ、Save Folderに保存。
縦線ノイズの検出・補正
自炊をしたことのある人ならおそらく誰もが悩むホコリによる「縦線ノイズ」を自動検知して修正します。
対象画像とパラメータとのバランスにかなり依存しますが、上手く設定すると「だいたいの縦線ノイズ」はちゃんと消してくれます。あらかじめ「コントラスト・濃度を調整するMacro」を使って黒ベタを真っ黒(信号値を0近辺)にしておくと検出力が安定し、仕上がりも綺麗になります。
ただ残念なことに、補正漏れや、「ノイズではない部分」を勝手に塗りつぶしちゃうことも多いのですが、なんとか実用可能なレベルかなと思います。
画像引用:吾峠呼世晴, 鬼滅の刃, コミックス第5巻, 57ページ, 集英社, 2017
定番のクイックルワイパーやメガネ拭き等を使って、スキャナ読み取り面のホコリ付着を防ぎつつスキャンし、それでも出てしまう縦線ノイズは、このマクロを使って夜寝てる間に検知+除去という使い方もアリだと思います。
後日ご紹介しようかとも思いますが、このMacroをいじって「検出のみ」に機能を削り、「修正」はImageJを使ってマニュアルで、という使い方も出来ます。マニュアル修正はポチポチ地道に塗りつぶす作業なので、修正するページ数が少ない場合だったら、この方法のほうが信頼性が高いと思います。
問題点
① 黒ベタじゃない部分の縦線と、縦線のはしっこ等の補正漏れ
② ノイズではない縦の白線部分も勝手に消しちゃう
③ 全自動だが時間がそれなりにかかる
④ コード内のパラメータ(セグメントの大きさ、閾値)あたりのバランスが微妙すぎて、ベストがわからん
このあたりでしょうか。シロウトがひぃひぃ言いながら作ったプログラムなので、正直これが今の限界です...。どなたかアドバイスをお願いします(切実)
パラメータについて補足
このプログラムは300dpiで「コントラスト・濃度を調整するMacro」を使用して黒ベタ部を0近辺まで下げたデータに対する処理を前提とした設定になっています。
もしもこれに沿わない場合は、縦線検出感度が強すぎたり弱すぎたりする可能性があるので、以下のパラメータを調整する必要があります。
・xSegOriginal, ySegOriginal...黒ベタ認識の区域分けの大きさ。大きすぎると長さの短い縦線ノイズを見逃すが、小さすぎると正常な縦線をノイズと誤認しやすくなる。dpiによっても変えるべき。
・TH_kuroBeta...この値より平均信号が低い (黒い) セグメントを黒ベタと認識する。高くすると認識感度は高くなり、低くすると感度は落ちる。補正したいデータの黒ベタ信号値によっても変えるべき。
・TH_whiteLine...黒ベタ認識後の長方形ROI走査で次のステップ(長方形ROI内の全信号値check)に進むための閾値。高くすると淡い縦線を検出出来ない。低くすると淡い縦線を検出しやすいが誤認増える。
・TH_HighIntensity...長方形ROI内全信号値checkの際に、「高信号である」と捉えるための閾値。TH_whiteLineと同じで良い気がする。
・TH_countRatio...長方形ROIの中に「高信号」が何%以上あるとノイズと認識するか。
・correctedValue...検出されたノイズ部をどんな値で埋めるか。黒ベタ部の信号で変えるべき。あらかじめコントラスト・濃度調整で黒ベタを0近辺まで落とし、ほぼ黒潰れさせた状態にしておいた上でcorrectedValueを0にするのが一番仕上がりが綺麗。
このパラメータ設定がキモなのですが、少しずつ値を変えながら自分なりのベストを見つけるのが大事です。(妥協はもっと大事)
マクロの起動方法
①ImageJ上部タブの[Plugins]→[New]→[Macro]で起動したエディタに、記事の一番上のコードをコピペしてtxtファイル(Vertical_Noise_Correction.txt)を作成・保存する。
②保存したファイルをImageJフォルダ内の[plugins]フォルダにしまう。
このとき、[plugins]フォルダの中に新たに適当な名前のフォルダを作って、その中にしまってもOKです。ここでは仮に「自炊」というフォルダにtxtファイルを突っ込んだとします。
③一度ImageJを再起動すると、マクロがインストールされ、起動準備OK。
④上部タブ[Plugins]→[自炊]→[Vertical Noise Correction]でマクロが実行されます。
注意
ImageJはPDFファイルをサポートしていないので、PDFで自炊している方はあらかじめ全てのファイルをJPGに直しておいて下さい!
Macの方はデフォルトでインストールされている「Automator」を使用するとJPGに直すことが出来ます。
ライセンスなんかは一切無いので、ぜひぜひ自由に使ってみてください!