縦線ノイズ、横線ノイズの自動検出・除去マクロの最新修正版のまとめです。
いちいち色んなページにいくのも大変だし、中身が古いバージョンのモノもあるので、ここで最新修正版をまとめて整理しちゃいます。
もくじ
- 1. フォルダ内全画像タテ線ノイズ自動除去
- 2. フォルダ内全画像ヨコ線ノイズ自動除去
- 3. 局所版タテ線ノイズ除去(選択範囲内のみ)
- 4. 局所版ヨコ線ノイズ除去(選択範囲内のみ)
- 5. ほどよいパラメータ見つけるマクロ(タテ線ノイズ用)
- 6. ほどよいパラメータ見つけるマクロ(ヨコ線ノイズ用)
- 7. おまけ : 画像保存に便利なマクロ
- マクロの起動方法
1. フォルダ内全画像タテ線ノイズ自動除去
フォルダ内全画像に対して、縦線ノイズ自動検出+除去を行います。検出・除去された画像のみ保存フォルダに保存されます。
//Vertical_Noise_Correction_HiSp.txt
version = "3.2.1";
print("ver",version);
setBatchMode(true);
//Do something for selected folder
showMessage("Select Open Folder");
openDir = getDirectory("Choose a Directory");
print("Processing :",openDir);
selectWindow("Log");
showMessage("Select Save Folder");
saveDir = getDirectory("Choose a Directory");
print("Save to :",saveDir);
selectWindow("Log");
list = getFileList(openDir);
wait(1000);
//JPEG, PNG quality(jpeg=90,gif=-1)
quality = 90;
run("Input/Output...", "jpeg=quality gif=-1 file=.csv save_column save_row");
//Output format
Dialog.create("Select Output Format");
items = newArray("JPEG", "PNG");
Dialog.addRadioButtonGroup("Output format", items, 1, 2, "JPEG");
Dialog.show;
output = Dialog.getRadioButton();
//--------Set Parameter--------------
//Segmentation setting
xSeg = 20;
ySeg = 20;
//BlackZone threshold(L_mean)
TH_kuroBeta = 50;
//WhiteLine threshold(s_mean)
TH_whiteLine = 20;
//HighIntensity threshold
TH_HighIntensity = 20;
//HighCount threshold
TH_countRatio = 90;
//-----------------------------------
//To prevent a memory shortage error
var x,y,sum,xStep,yStep,depth,segCount,xi,yi,pixelValue,detectedCount,rejectCounter,correctCount;
var saveFlag,width,height,L_mean,a,b,s_mean,count,ii,jj,pixel_intensity,iii,beta,correctedValue;
var xSeg,ySeg,TH_kuroBeta,TH_whiteLine,TH_HighIntensity,TH_countRatio,seed;
//operation
startTime = whatTimeNow();
x = 0;
y = 0;
detectedCount = 0;
rejectCounter = 0;
for (i=0; i<list.length;i++){
open(openDir+list[i]);
//progress
print(i+1,"/",list.length,"...Progress=",floor((i+1)/list.length*10000)/100,"%");
memory = IJ.currentMemory();
memory = parseInt(memory)/1000000;
print("Current Memmory=",d2s(memory,2),"MB");
saveFlag = 0;
correctCount = 0;
sum = 0;
width = getWidth();
height = getHeight();
//value of movement
xStep = floor(xSeg/2);
yStep = floor(ySeg/2);
depth = bitDepth();
if (depth == 8) {
//Segmentation section
segCount = 1;
for(y=0; y<height-ySeg; y=y+yStep){
for(x=0; x<width-xSeg; x=x+xStep){
for(xi=0; xi<xSeg; xi++){
for(yi=0; yi<ySeg; yi++){
pixelValue = getPixel(x+xi,y+yi);
sum = sum+pixelValue;
}
}
L_mean = sum/xSeg/ySeg;
sum = 0;
//print(i+1,"/",list.length,"...Progress=",floor((i+1)/list.length*10000)/100,"%",", ","Segment No=",segCount);
segCount++;
//recognize kuroBeta
if(L_mean < TH_kuroBeta){
a = x+5; //exclude both ends of image (5+5 pixels)
b = y;
//small rectangle ROI scan
for(ii=0; ii<xSeg-10; ii++){
b = y; //reset b (++ by jj_loop)
for(yi=0; yi<ySeg; yi++){
pixelValue = getPixel(a,b+yi);
sum = sum+pixelValue;
}
s_mean = sum/ySeg;
sum = 0;
//vertical direction scan on detected whiteLine
if(s_mean > TH_whiteLine){
count = 0;
for(jj=0; jj<ySeg; 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("(",a,",",b,")","Noise Correction!!",correctCount);
saveFlag = 1;
b = y;
for(iii=0; iii<ySeg; iii++){
seed = random(); //between 0 and 1
beta = L_mean-seed*10;
if(beta < 0) beta = 0;
correctedValue = floor(beta);
setPixel(a,b,correctedValue);
b = b+1;
}
}
}
a = a+1; //in ii_loop
}
}
}
}
}else{
rejectCounter++;
print("...Color Image!");
}
if(saveFlag == 1){
name = getTitle();
dotIndex = lastIndexOf(name,".");
title = substring(name,0,dotIndex);
if (output == "JPEG") newname = title+".jpg";
else if (output == "PNG") newname = title+".png";
rename(newname);
if (output == "JPEG") saveAs("Jpeg", saveDir+newname);
else if (output == "PNG") saveAs("PNG", saveDir+newname);
detectedCount++;
}
close();
}
//fin
finishTime = whatTimeNow();
print("DetectedCounts=",detectedCount);
print("Start Time .... ",startTime);
print("FinishTime ... ",finishTime);
print("oshimai");
//-----------------------------------------------------------------------------
//Define function whatTimeNow
function whatTimeNow(){
getDateAndTime(year,month,dayOfWeek,dayOfMonth,hour,minute,second,msec);
stringTime = "string";
strYear = ""+year;
month = month+1;
if(month < 10){
strMonth = "0"+month;
}else{
strMonth = ""+month;
}
if(dayOfMonth < 10){
strDayOfMonth = "0"+dayOfMonth;
}else{
strDayOfMonth = ""+dayOfMonth;
}
if(hour < 10){
strHour = "0"+hour;
}else{
strHour = ""+hour;
}
if(minute < 10){
strMinute = "0"+minute;
}else{
strMinute = ""+minute;
}
if(second < 10){
strSecond = "0"+second;
}else{
strSecond = ""+second;
}
stringTime = strYear+"/"+strMonth+"/"+strDayOfMonth+"_"+strHour+":"+strMinute+":"+strSecond;
return stringTime;
}
//-----------------------------------------------------------------------------
2020.04.08. 追記
書き出しフォーマット(JPEG, PNG)をダイアログから選択出来るように修正しました。
2021.11.07. 追記
解析過程のLogを表示させることが使用メモリ過多の原因となっていたので、改善しました。
コード内容紹介ページ
2. フォルダ内全画像ヨコ線ノイズ自動除去
フォルダ内全画像に対して、横向きスキャン時の横線ノイズ自動検出+除去を行います。検出・除去された画像のみ保存フォルダに保存されます。
//Horizontal_Noise_Correction_HiSp.txt
version = "3.4.1";
print("ver",version);
setBatchMode(true);
//Do something for selected folder
showMessage("Select Open Folder");
openDir = getDirectory("Choose a Directory");
print("Processing :",openDir);
selectWindow("Log");
showMessage("Select Save Folder");
saveDir = getDirectory("Choose a Directory");
print("Save to :",saveDir);
selectWindow("Log");
list = getFileList(openDir);
wait(1000);
//JPEG, PNG quality(jpeg=90,gif=-1)
quality = 90;
run("Input/Output...", "jpeg=quality gif=-1 file=.csv save_column save_row");
//Output format
Dialog.create("Select Output Format");
items = newArray("JPEG", "PNG");
Dialog.addRadioButtonGroup("Output format", items, 1, 2, "JPEG");
Dialog.show;
output = Dialog.getRadioButton();
//--------Set Parameter--------------
//Segmentation setting
xSeg = 20;
ySeg = 20;
//BlackZone threshold(L_mean)
TH_kuroBeta = 50;
//WhiteLine threshold(s_mean)
TH_whiteLine = 20;
//HighIntensity threshold
TH_HighIntensity = 20;
//HighCount threshold
TH_countRatio = 90;
//-----------------------------------
//To prevent a memory shortage error
var x,y,sum,xStep,yStep,depth,segCount,xi,yi,pixelValue,detectedCount,rejectCounter,correctCount;
var saveFlag,width,height,L_mean,a,b,s_mean,count,ii,jj,pixel_intensity,iii,beta,correctedValue;
var xSeg,ySeg,TH_kuroBeta,TH_whiteLine,TH_HighIntensity,TH_countRatio,seed;
//operation
startTime = whatTimeNow();
x = 0;
y = 0;
detectedCount = 0;
rejectCounter = 0;
for (i=0; i<list.length;i++){
open(openDir+list[i]);
run("Rotate 90 Degrees Right");
//progress
print(i+1,"/",list.length,"...Progress=",floor((i+1)/list.length*10000)/100,"%");
memory = IJ.currentMemory();
memory = parseInt(memory)/1000000;
print("Current Memmory=",d2s(memory,2),"MB");
saveFlag = 0;
correctCount = 0;
sum = 0;
width = getWidth();
height = getHeight();
//value of movement
xStep = floor(xSeg/2);
yStep = floor(ySeg/2);
depth = bitDepth();
if (depth == 8) {
//Segmentation section
segCount = 1;
for(y=0; y<height-ySeg; y=y+yStep){
for(x=0; x<width-xSeg; x=x+xStep){
for(xi=0; xi<xSeg; xi++){
for(yi=0; yi<ySeg; yi++){
pixelValue = getPixel(x+xi,y+yi);
sum = sum+pixelValue;
}
}
L_mean = sum/xSeg/ySeg;
sum = 0;
//print(i+1,"/",list.length,"...Progress=",floor((i+1)/list.length*10000)/100,"%",", ","Segment No=",segCount);
segCount++;
//recognize kuroBeta
if(L_mean < TH_kuroBeta){
a = x+5; //exclude both ends of image (5+5 pixels)
b = y;
//small rectangle ROI scan
for(ii=0; ii<xSeg-10; ii++){
b = y; //reset b (++ by jj_loop)
for(yi=0; yi<ySeg; yi++){
pixelValue = getPixel(a,b+yi);
sum = sum+pixelValue;
}
s_mean = sum/ySeg;
sum = 0;
//horizontal direction scan on detected whiteLine
if(s_mean > TH_whiteLine){
count = 0;
for(jj=0; jj<ySeg; 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("(",a,",",b,")","Noise Correction!!",correctCount);
saveFlag = 1;
b = y;
for(iii=0; iii<ySeg; iii++){
seed = random(); //between 0 and 1
beta = L_mean-seed*10;
if(beta < 0) beta = 0;
correctedValue = floor(beta);
setPixel(a,b,correctedValue);
b = b+1;
}
}
}
a = a+1; //in ii_loop
}
}
}
}
}else{
rejectCounter++;
print("...Color Image!");
}
if(saveFlag == 1){
run("Rotate 90 Degrees Left");
name = getTitle();
dotIndex = lastIndexOf(name,".");
title = substring(name,0,dotIndex);
if (output == "JPEG") newname = title+".jpg";
else if (output == "PNG") newname = title+".png";
rename(newname);
if (output == "JPEG") saveAs("Jpeg", saveDir+newname);
else if (output == "PNG") saveAs("PNG", saveDir+newname);
detectedCount++;
}
close();
}
//fin
finishTime = whatTimeNow();
print("DetectedCounts=",detectedCount);
print("Start Time .... ",startTime);
print("FinishTime ... ",finishTime);
print("oshimai");
//-----------------------------------------------------------------------------
//Define function whatTimeNow
function whatTimeNow(){
getDateAndTime(year,month,dayOfWeek,dayOfMonth,hour,minute,second,msec);
stringTime = "string";
strYear = ""+year;
month = month+1;
if(month < 10){
strMonth = "0"+month;
}else{
strMonth = ""+month;
}
if(dayOfMonth < 10){
strDayOfMonth = "0"+dayOfMonth;
}else{
strDayOfMonth = ""+dayOfMonth;
}
if(hour < 10){
strHour = "0"+hour;
}else{
strHour = ""+hour;
}
if(minute < 10){
strMinute = "0"+minute;
}else{
strMinute = ""+minute;
}
if(second < 10){
strSecond = "0"+second;
}else{
strSecond = ""+second;
}
stringTime = strYear+"/"+strMonth+"/"+strDayOfMonth+"_"+strHour+":"+strMinute+":"+strSecond;
return stringTime;
}
//-----------------------------------------------------------------------------
コード内容紹介ページ
3. 局所版タテ線ノイズ除去(選択範囲内のみ)
縦線のある画像に対して、ROI(四角の枠線 : ImageJのRectangle Tool)を用いて範囲を選択し、範囲内に限定した自動検出+除去を行います。保存は手動で行ってください。
//Local_Vertical_Noise_Correction_HiSp.txt
//Segmentation setting
xSeg = 20;
ySeg = 20;
//BlackZone threshold(L_mean)
TH_kuroBeta = 50;
//WhiteLine threshold(s_mean)
TH_whiteLine = 15;
//HighIntensity threshold
TH_HighIntensity = 15;
//HighCount threshold
TH_countRatio = 80;
//operation
var correctCount = 0;
getSelectionBounds(x0,y0,width,height);
VNC();
function VNC(){
x = x0;
y = y0;
sum = 0;
//value of movement
xStep = floor(xSeg/2);
yStep = floor(ySeg/2);
depth = bitDepth();
if (depth == 8) {
//Segmentation section
segCount = 1;
for(y=y0; y<y0+height-ySeg; y=y+yStep){
for(x=x0; x<x0+width-xSeg; x=x+xStep){
for(xi=0; xi<xSeg; xi++){
for(yi=0; yi<ySeg; yi++){
pixelValue = getPixel(x+xi,y+yi);
sum = sum+pixelValue;
}
}
L_mean = sum/xSeg/ySeg;
sum = 0;
print("Segment No=",segCount);
segCount++;
//recognize kuroBeta
if(L_mean < TH_kuroBeta){
a = x+5;
b = y;
//small rectangle ROI scan
for(ii=0; ii<xSeg-10; ii++){
b = y;
for(yi=0; yi<ySeg; yi++){
pixelValue = getPixel(a,b+yi);
sum = sum+pixelValue;
}
s_mean = sum/ySeg;
sum = 0;
//vertical direction scan on detected whiteLine
if(s_mean > TH_whiteLine){
count = 0;
for(jj=0; jj<ySeg; 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("(",a,",",b,")","Noise Correction!!",correctCount);
b = y;
for(iii=0; iii<ySeg; iii++){
seed = random();
beta = L_mean-seed*10;
if(beta < 0) beta = 0;
correctedValue = floor(beta);
setPixel(a,b,correctedValue);
b = b+1;
}
}
}
a = a+1;
}
}
}
}
}else{
print("...Color Image!");
}
}
print("correctCount=",correctCount);
print("oshimai");
コード内容紹介ページ
4. 局所版ヨコ線ノイズ除去(選択範囲内のみ)
横線のある画像に対して、ROI(四角の枠線 : ImageJのRectangle Tool)を用いて範囲を選択し、範囲内に限定した自動検出+除去を行います。保存は手動で行ってください。
//Local_Horizontal_Noise_Correction_HiSp.txt
//Segmentation setting
xSeg = 20;
ySeg = 20;
//BlackZone threshold(L_mean)
TH_kuroBeta = 50;
//WhiteLine threshold(s_mean)
TH_whiteLine = 15;
//HighIntensity threshold
TH_HighIntensity = 15;
//HighCount threshold
TH_countRatio = 80;
//correctedValue setting
correctedValue = 0;
//operation
var correctCount = 0;
getSelectionBounds(x0,y0,width,height);
HNC();
function HNC(){
x = x0;
y = y0;
sum = 0;
//value of movement
xStep = floor(xSeg/2);
yStep = floor(ySeg/2);
depth = bitDepth();
if (depth == 8) {
//Segmentation section
segCount = 1;
for(y=y0; y<y0+height-ySeg; y=y+yStep){
for(x=x0; x<x0+width-xSeg; x=x+xStep){
for(xi=0; xi<xSeg; xi++){
for(yi=0; yi<ySeg; yi++){
pixelValue = getPixel(x+xi,y+yi);
sum = sum+pixelValue;
}
}
L_mean = sum/xSeg/ySeg;
sum = 0;
print("Segment No=",segCount);
segCount++;
//recognize kuroBeta
if(L_mean < TH_kuroBeta){
a = x;
b = y+5;
//small rectangle ROI scan
for(ii=0; ii<ySeg-10; ii++){
a = x;
for(xi=0; xi<xSeg; xi++){
pixelValue = getPixel(a+xi,b);
sum = sum+pixelValue;
}
s_mean = sum/xSeg;
sum = 0;
//horizontal direction scan on detected whiteLine
if(s_mean > TH_whiteLine){
count = 0;
for(jj=0; jj<xSeg; jj++){
pixel_intensity = getPixel(a,b);
//count HighIntensity
if(pixel_intensity > TH_HighIntensity){
count++;
a++;
}
}
//Noise Correction
if(count > ySeg*TH_countRatio/100){
correctCount++;
print("(",a,",",b,")","Noise Correction!!",correctCount);
a = x;
for(iii=0; iii<xSeg; iii++){
seed = random();
beta = L_mean-seed*10;
if(beta < 0) beta = 0;
correctedValue = floor(beta);
setPixel(a,b,correctedValue);
a = a+1;
}
}
}
b = b+1;
}
}
}
}
}else{
print("...Color Image!");
}
}
print("correctCount=",correctCount);
print("oshimai");
コード内容紹介ページ
5. ほどよいパラメータ見つけるマクロ(タテ線ノイズ用)
初出しです。ほどよいパラメータを見つけるために、パラメータを変えながら何度も処理を試したい時に使ってください。ここで見つけたパラメータを上記の「フォルダ内全画像自動処理版」や「局所版」に打ち込みましょう。
//Local_VNC_AdjustParameters.txt
//Segmentation setting
xSeg = 20;
ySeg = 20;
//BlackZone threshold(L_mean)
TH_kuroBeta = 50;
//WhiteLine threshold(s_mean)
TH_whiteLine = 15;
//HighIntensity threshold
TH_HighIntensity = 15;
//HighCount threshold
TH_countRatio = 80;
//To prevent a memory shortage error
var x,y,sum,xStep,yStep,depth,segCount,xi,yi,pixelValue,correctCount;
var L_mean,a,b,s_mean,count,ii,jj,pixel_intensity,iii,beta,correctedValue;
var xSeg,ySeg,TH_kuroBeta,TH_whiteLine,TH_HighIntensity,TH_countRatio,seed,endFlag;
//operation
endFlag = 1;
correctCount = 0;
getSelectionBounds(x0,y0,width,height);
if(endFlag == 1)VNCtest();
function VNCtest(){
Dialog.create("Parameters")
Dialog.addNumber("xSeg",xSeg);
Dialog.addNumber("ySeg",ySeg);
Dialog.addNumber("TH_kuroBeta",TH_kuroBeta);
Dialog.addNumber("TH_whiteLine",TH_whiteLine);
Dialog.addNumber("TH_HighIntensity",TH_HighIntensity);
Dialog.addNumber("TH_countRatio",TH_countRatio);
Dialog.show;
xSeg = Dialog.getNumber();
ySeg = Dialog.getNumber();
TH_kuroBeta = Dialog.getNumber();
TH_whiteLine = Dialog.getNumber();
TH_HighIntensity = Dialog.getNumber();
TH_countRatio = Dialog.getNumber();
x = x0;
y = y0;
sum = 0;
//value of movement
xStep = floor(xSeg/2);
yStep = floor(ySeg/2);
depth = bitDepth();
if (depth == 8) {
//Segmentation section
segCount = 1;
for(y=y0; y<y0+height-ySeg; y=y+yStep){
for(x=x0; x<x0+width-xSeg; x=x+xStep){
for(xi=0; xi<xSeg; xi++){
for(yi=0; yi<ySeg; yi++){
pixelValue = getPixel(x+xi,y+yi);
sum = sum+pixelValue;
}
}
L_mean = sum/xSeg/ySeg;
sum = 0;
print("Segment No=",segCount);
segCount++;
//recognize kuroBeta
if(L_mean < TH_kuroBeta){
a = x+5;
b = y;
//small rectangle ROI scan
for(ii=0; ii<xSeg-10; ii++){
b = y;
for(yi=0; yi<ySeg; yi++){
pixelValue = getPixel(a,b+yi);
sum = sum+pixelValue;
}
s_mean = sum/ySeg;
sum = 0;
//vertical direction scan on detected whiteLine
if(s_mean > TH_whiteLine){
count = 0;
for(jj=0; jj<ySeg; 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("(",a,",",b,")","Noise Correction!!",correctCount);
b = y;
for(iii=0; iii<ySeg; iii++){
seed = random();
beta = L_mean-seed*10;
if(beta < 0) beta = 0;
correctedValue = floor(beta);
setPixel(a,b,correctedValue);
b = b+1;
}
}
}
a = a+1;
}
}
}
}
}else{
print("...Color Image!");
}
print("correctCount=",correctCount);
waitForUser("Click image and check effect of noise correction");
endFlag = getBoolean(" Again?\n [Yes]...Change parameters and retry.\n [No]...Confirm results.");
if(endFlag == 1){
run("Revert");
VNCtest();
}
else if(endFlag == 0){
print("------Parameters------");
print("xSeg =",xSeg);
print("ySeg =",ySeg);
print("TH_kuroBeta =",TH_kuroBeta);
print("TH_whiteLine =",TH_whiteLine);
print("TH_HighIntensity =",TH_HighIntensity);
print("TH_countRatio =",TH_countRatio);
print("oshimai");
}
}
6. ほどよいパラメータ見つけるマクロ(ヨコ線ノイズ用)
上記5と同じく初出しです。ほどよいパラメータを見つけるために、パラメータを変えながら何度も処理を試したい時に使ってください。ここで見つけたパラメータを上記の「フォルダ内全画像自動処理版」や「局所版」に打ち込みましょう。
//Local_HNC_AdjustParameters.txt
//Segmentation setting
xSeg = 20;
ySeg = 20;
//BlackZone threshold(L_mean)
TH_kuroBeta = 50;
//WhiteLine threshold(s_mean)
TH_whiteLine = 15;
//HighIntensity threshold
TH_HighIntensity = 15;
//HighCount threshold
TH_countRatio = 80;
//To prevent a memory shortage error
var x,y,sum,xStep,yStep,depth,segCount,xi,yi,pixelValue,correctCount;
var L_mean,a,b,s_mean,count,ii,jj,pixel_intensity,iii,beta,correctedValue;
var xSeg,ySeg,TH_kuroBeta,TH_whiteLine,TH_HighIntensity,TH_countRatio,seed,endFlag;
//operation
endFlag = 1;
correctCount=0;
getSelectionBounds(x0,y0,width,height);
if(endFlag == 1)HNCtest();
function HNCtest(){
Dialog.create("Parameters")
Dialog.addNumber("xSeg",xSeg);
Dialog.addNumber("ySeg",ySeg);
Dialog.addNumber("TH_kuroBeta",TH_kuroBeta);
Dialog.addNumber("TH_whiteLine",TH_whiteLine);
Dialog.addNumber("TH_HighIntensity",TH_HighIntensity);
Dialog.addNumber("TH_countRatio",TH_countRatio);
Dialog.show;
xSeg = Dialog.getNumber();
ySeg = Dialog.getNumber();
TH_kuroBeta = Dialog.getNumber();
TH_whiteLine = Dialog.getNumber();
TH_HighIntensity = Dialog.getNumber();
TH_countRatio = Dialog.getNumber();
x = x0;
y = y0;
sum = 0;
//value of movement
xStep = floor(xSeg/2);
yStep = floor(ySeg/2);
depth = bitDepth();
if (depth == 8) {
//Segmentation section
segCount = 1;
for(y=y0; y<y0+height-ySeg; y=y+yStep){
for(x=x0; x<x0+width-xSeg; x=x+xStep){
for(xi=0; xi<xSeg; xi++){
for(yi=0; yi<ySeg; yi++){
pixelValue = getPixel(x+xi,y+yi);
sum = sum+pixelValue;
}
}
L_mean = sum/xSeg/ySeg;
sum = 0;
print("Segment No=",segCount);
segCount++;
//recognize kuroBeta
if(L_mean < TH_kuroBeta){
a = x;
b = y+5;
//small rectangle ROI scan
for(ii=0; ii<ySeg-10; ii++){
a = x;
for(xi=0; xi<xSeg; xi++){
pixelValue = getPixel(a+xi,b);
sum = sum+pixelValue;
}
s_mean = sum/xSeg;
sum = 0;
//horizontal direction scan on detected whiteLine
if(s_mean > TH_whiteLine){
count = 0;
for(jj=0; jj<xSeg; jj++){
pixel_intensity = getPixel(a,b);
//count HighIntensity
if(pixel_intensity > TH_HighIntensity){
count++;
a++;
}
}
//Noise Correction
if(count > ySeg*TH_countRatio/100){
correctCount++;
print("(",a,",",b,")","Noise Correction!!",correctCount);
a = x;
for(iii=0; iii<xSeg; iii++){
seed = random();
beta = L_mean-seed*10;
if(beta < 0) beta = 0;
correctedValue = floor(beta);
setPixel(a,b,correctedValue);
a = a+1;
}
}
}
b = b+1;
}
}
}
}
}else{
print("...Color Image!");
}
print("correctCount=",correctCount);
waitForUser("Click image and check effect of noise correction");
endFlag = getBoolean(" Again?\n [Yes]...Change parameters and retry.\n [No]...Confirm results.");
if(endFlag == 1){
run("Revert");
HNCtest();
}
else if(endFlag == 0){
print("------Parameters------");
print("xSeg =",xSeg);
print("ySeg =",ySeg);
print("TH_kuroBeta =",TH_kuroBeta);
print("TH_whiteLine =",TH_whiteLine);
print("TH_HighIntensity =",TH_HighIntensity);
print("TH_countRatio =",TH_countRatio);
print("oshimai");
}
}
ちなみにパラメータの推奨値ですが、私の場合(EPSON製DS530で、明るさ0、コントラスト15、ガンマ2.2、400dpi)では、
xSeg = 20;
ySeg = 20;
TH_kuroBeta = 50;
TH_whiteLine = 15;
TH_HighIntensity = 15;
TH_countRatio = 80;
です。ここからちまちまと確認・微調整して使っています。参考までに。
7. おまけ : 画像保存に便利なマクロ
最後に、画像保存用マクロです。局所版で補正した画像を、ショートカットに登録した下記マクロで保存すると捗ります。
◆JPEG保存用
//Save_As_JPEG_to_DeskTop.txt
saveDir = "/Users/Yu3xx/Desktop/";
//JPEG Quality
run("Input/Output...", "jpeg=90 gif=-1 file=.csv save_column save_row");
name = getTitle;
dotIndex = lastIndexOf(name, ".");
title = substring(name, 0, dotIndex);
newname = title+".jpg";
rename(newname);
saveAs("Jpeg", saveDir+newname);
close(newname);
print("Save OK by JPEG...",newname);
◆PNG保存用
//Save_As_PNG_to_DeskTop.txt
saveDir = "/Users/Yu3xx/Desktop/";
//PNG setting(gif=-1)
run("Input/Output...", "jpeg=90 gif=-1 file=.csv save_column save_row");
name = getTitle;
dotIndex = lastIndexOf(name, ".");
title = substring(name, 0, dotIndex);
newname = title+".png";
rename(newname);
saveAs("PNG", saveDir+newname);
close(newname);
print("Save OK by PNG...",newname);
※1 保存先パスは使用しているPCに合わせて書き換えてください。
Windowsの場合、C:¥¥Users¥¥yu3xx¥¥Desktop¥¥(円は半角!)になります。
※2 (ショートカット登録は、マクロをインストール(再起動)したあと、上部タブ[Plugins]→[Shortcuts]→[Add shortcut]。私の場合は0にJPEG、9にPNGを入れています。)
マクロの起動方法
①ImageJ上部タブの[Plugins]→[New]→[Macro]で起動したエディタに、記事内のコードをそれぞれコピペしてtxtファイル(Vertical_Noise_Correction_HiSp.txtなど)を作成・保存する。
②保存したファイルをImageJフォルダ内の[plugins]フォルダにしまう。
このとき、[plugins]フォルダの中に新たに適当な名前のフォルダを作って、その中にしまってもOKです。ここでは仮に「自炊」というフォルダにtxtファイルを突っ込んだとします。
③一度ImageJを再起動すると、マクロがインストールされ、起動準備OK。
④上部タブ[Plugins]→[自炊]→[Vertical Noise Correctionなどなど]でマクロが実行されます。
ライセンスなんかは一切無いので、ぜひぜひ自由に使ってみてください!