using System;
using System.Windows.Forms;
using System.IO;
using System.Drawing;
using System.Drawing.Imaging;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Threading;
using System.Diagnostics;
using System.Linq;
using System.Collections.Generic;
using TensorFlow;
using OpenCvSharp;
namespace Tongue_extraction
{
public partial class Form1 : Form
{
//Use the RemoveSmallRegionDLL
[DllImport(@"RemoveSmallRegionDLL.dll", EntryPoint = "RemoveSmallRegion", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = false, CallingConvention = CallingConvention.StdCall)]
extern static void RemoveSmallRegion(string name, string name2, int AreaLimit, int CheckMode, int NeihborMode);
Mat mat_drawBox = new Mat(1024, 1280, MatType.CV_8UC3, 1);
Mat mat_roi = new Mat(1024, 1280, MatType.CV_8UC3, 1);
Mat mat_input = new Mat(1024, 1280, MatType.CV_8UC3, 1);
Mat mat_roi256 = new Mat(256, 256, MatType.CV_8UC3, 1);
Mat mat_roisize = new Mat(1024, 1280, MatType.CV_8UC3, 1);
Mat mat_output = new Mat(1024, 1280, MatType.CV_8UC1, 1);
Mat mat_outputNoBox = new Mat(1024, 1280, MatType.CV_8UC1, 1);
Mat mat_outputChanged = new Mat(1024, 1280, MatType.CV_8UC1, 1);
Mat mat_mask = new Mat(1024, 1280, MatType.CV_8UC1, 1);
Mat mat_extraction = new Mat(1024, 1280, MatType.CV_8UC3, 1);
Mat mat_cropped;
Mat mat_outputSRGNoBox = new Mat(1024, 1280, MatType.CV_8UC1, 1);
Mat mat_outputSRG = new Mat(1024, 1280, MatType.CV_8UC1, 1);
Mat mat_maskSRG = new Mat(1024, 1280, MatType.CV_8UC1, 1);
public static Bitmap bitmap_bitch;
OpenCvSharp.Rect rectangle;
byte[] byte_inputDetection;
byte[] byte_inputSegmentation;
OpenCvSharp.Point P1 = new OpenCvSharp.Point();
OpenCvSharp.Point P2 = new OpenCvSharp.Point();
byte[] mask = new byte[200000];
string basepath;
string imageFile;
string time;
string modelFile;
int ii = 0;
int count;
int areaCount;
Rect roi = new Rect();
int mmp = 0;
int pmm = 0;
int check_detection = 0;
float max_score = 0;
private ManualResetEvent manualReset = new ManualResetEvent(true);
string path_infocsv = Directory.GetCurrentDirectory() + "//info//" + DateTime.Now.ToLocalTime().ToString("yyyyMMddhhmmss") + ".csv";
string path_procList = @"ProcList.txt";
bool IsLastFileChanged = false;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
comboBox_mode.SelectedIndex = 2;
}
private void Button_start_Click(object sender, EventArgs e)
{
button_start.Enabled = false;
button_pause.Enabled = true;
pictureBox_input.Image = null;
pictureBox_input.Refresh();
pictureBox_detection.Image = null;
pictureBox_detection.Refresh();
pictureBox_cropResized.Image = null;
pictureBox_cropResized.Refresh();
pictureBox_output.Image = null;
pictureBox_output.Refresh();
pictureBox_outputSRG.Image = null;
pictureBox_outputSRG.Refresh();
pictureBox_maskSRG.Image = null;
pictureBox_maskSRG.Refresh();
pictureBox_extraction.Image = null;
pictureBox_extraction.Refresh();
pictureBox_last.Image = null;
pictureBox_last.Refresh();
comboBox_mode.Enabled = false;
if (comboBox_mode.SelectedIndex == 0)
{
// 画像のみ入力し,マスク等を得る
this.backgroundWorker1.DoWork += new System.ComponentModel.DoWorkEventHandler(this.BackgroundWorker1_DoWork_Image);
backgroundWorker1.RunWorkerAsync();
}
else if (comboBox_mode.SelectedIndex == 1)
{
// 画像と校正画像を入力し,Lab色を得る
this.backgroundWorker1.DoWork += new System.ComponentModel.DoWorkEventHandler(this.BackgroundWorker1_DoWork_ImageandCalib);
backgroundWorker1.RunWorkerAsync();
}
else if (comboBox_mode.SelectedIndex == 2)
{
// TIASフォルダを入力し,Lab色を得る
this.backgroundWorker1.DoWork += new System.ComponentModel.DoWorkEventHandler(this.BackgroundWorker1_DoWork_TIASdata);
backgroundWorker1.RunWorkerAsync();
}
else
{
MessageBox.Show("Please select the mode on the combobox");
}
}
public static class ImageUtil
{
// Convert the image in filename to a Tensor suitable as input to the Inception model.
public static TFTensor CreateTensorFromImageFile(byte[] contents, TFDataType destinationDataType = TFDataType.UInt8)
{
// DecodeJpeg uses a scalar String-valued tensor as input.
var tensor = TFTensor.CreateString(contents);
TFGraph graph;
TFOutput input, output;
// Construct a graph to normalize the image
ConstructGraphToNormalizeImage(out graph, out input, out output, destinationDataType);
// Execute that graph to normalize this one image
using (var session = new TFSession(graph))
{
var normalized = session.Run(
inputs: new[] { input },
inputValues: new[] { tensor },
outputs: new[] { output });
if (session != null)
{
session.Dispose();
}
if (tensor != null)
{
tensor.Dispose();
}
if (graph != null)
{
graph.Dispose();
}
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
return normalized[0];
}
}
// The inception model takes as input the image described by a Tensor in a very
// specific normalized format (a particular image size, shape of the input tensor,
// normalized pixel values etc.).
//
// This function constructs a graph of TensorFlow operations which takes as
// input a JPEG-encoded string and returns a tensor suitable as input to the
// inception model.
public static void ConstructGraphToNormalizeImage(out TFGraph graph, out TFOutput input, out TFOutput output, TFDataType destinationDataType = TFDataType.UInt8)
{
const int W = 256;
const int H = 256;
const float Mean = 0;
const float Scale = 1;
graph = new TFGraph();
input = graph.Placeholder(TFDataType.String);
output = graph.Cast(graph.Div(
x: graph.Sub(
x: graph.ResizeBilinear(
images: graph.ExpandDims(
input: graph.Cast(
graph.DecodeJpeg(contents: input, channels: 3), DstT: destinationDataType),
dim: graph.Const(0, "make_batch")),
size: graph.Const(new int[] { W, H }, "size")),
y: graph.Const(Mean, "mean")),
y: graph.Const(Scale, "scale")), destinationDataType);
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
}
}
public static class ImageUtil2
{
// Convert the image in filename to a Tensor suitable as input to the Inception model.
public static TFTensor CreateTensorFromImageFile(byte[] contents, TFDataType destinationDataType = TFDataType.Float)
{
// DecodeJpeg uses a scalar String-valued tensor as input.
var tensor = TFTensor.CreateString(contents);
TFGraph graph;
TFOutput input, output;
// Construct a graph to normalize the image
ConstructGraphToNormalizeImage(out graph, out input, out output, destinationDataType);
// Execute that graph to normalize this one image
using (var session = new TFSession(graph))
{
var normalized = session.Run(
inputs: new[] { input },
inputValues: new[] { tensor },
outputs: new[] { output });
if (session != null)
{
session.Dispose();
}
if (tensor != null)
{
tensor.Dispose();
}
if (graph != null)
{
graph.Dispose();
}
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
return normalized[0];
}
}
// The inception model takes as input the image described by a Tensor in a very
// specific normalized format (a particular image size, shape of the input tensor,
// normalized pixel values etc.).
//
// This function constructs a graph of TensorFlow operations which takes as
// input a JPEG-encoded string and returns a tensor suitable as input to the
// inception model.
public static void ConstructGraphToNormalizeImage(out TFGraph graph, out TFOutput input, out TFOutput output, TFDataType destinationDataType = TFDataType.Float)
{
const int W = 256;
const int H = 256;
//const int W = 512;
//const int H = 512;
const float Mean = 128;
const float Scale = 128;
graph = new TFGraph();
input = graph.Placeholder(TFDataType.String);
output = graph.Cast(graph.Div(
x: graph.Sub(
x: graph.ResizeBilinear(
images: graph.ExpandDims(
input: graph.Cast(
graph.DecodeJpeg(contents: input, channels: 3), DstT: TFDataType.Float),
dim: graph.Const(0, "make_batch")),
size: graph.Const(new int[] { W, H }, "size")),
y: graph.Const(Mean, "mean")),
y: graph.Const(Scale, "scale")), destinationDataType);
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
}
}
public static byte[] Bitmap2Byte(Bitmap bitmap)
{
using (MemoryStream stream = new MemoryStream())
{
bitmap.Save(stream, ImageFormat.Jpeg);
byte[] data = new byte[stream.Length];
stream.Seek(0, SeekOrigin.Begin);
stream.Read(data, 0, Convert.ToInt32(stream.Length));
return data;
}
}
private static string DownloadDefaultModel(string dir)
{
var modelFile = Path.Combine(dir, "pruning101_step11999.pb");
return modelFile;
}
private static string DownloadDefaultModel_noBoxPix2Pix(string dir)
{
var modelFile = Path.Combine(dir, "424_256_64_5999_scale300_enhancment_L1loss0.02001.pb");
return modelFile;
}
public static Bitmap ToGrayBitmap(byte[] rawValues, int width, int height)
{
//// Apply for a target bitmap variable and lock its memory area
Bitmap bmp = new Bitmap(width, height, PixelFormat.Format8bppIndexed);
BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, width, height),
ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed);
//// Get image parameters
int stride = bmpData.Stride; // Width of the scan line
int offset = stride - width; // Show gap between width and scan line width
IntPtr iptr = bmpData.Scan0; // Get the memory start position of bmpData
int scanBytes = stride * height;// Use stride width to indicate that this is the size of the memory area
//// The following is to convert the original display size byte array to the byte array actually stored in memory.
int posScan = 0, posReal = 0;// Set two position pointers respectively, pointing to the source array and the target array
byte[] pixelValues = new byte[scanBytes]; //Allocate memory for the target array
for (int x = 0; x < height; x++)
{
//// The following loop section is a simulated line scan
for (int y = 0; y < width; y++)
{
pixelValues[posScan++] = rawValues[posReal++];
}
posScan += offset; //At the end of the line scan, move the target position pointer over that "gap"
}
//// Use Marshal's Copy method to copy the just obtained memory byte array into BitmapData.
System.Runtime.InteropServices.Marshal.Copy(pixelValues, 0, iptr, scanBytes);
bmp.UnlockBits(bmpData); // Unlock the memory area
//// The following code is to modify the index table of the generated bitmap, from pseudo color to grayscale
ColorPalette tempPalette;
using (Bitmap tempBmp = new Bitmap(1, 1, PixelFormat.Format8bppIndexed))
{
tempPalette = tempBmp.Palette;
}
for (int i = 0; i < 256; i++)
{
tempPalette.Entries[i] = Color.FromArgb(i, i, i);
}
bmp.Palette = tempPalette;
//// The algorithm ends here and returns the result.
return bmp;
}
private void BackgroundWorker1_DoWork_Image(object sender, DoWorkEventArgs e)
{
MessageBox.Show("this mode isn't implemented");
}
private void BackgroundWorker1_DoWork_ImageandCalib(object sender, DoWorkEventArgs e)
{
// boundingboxなどのinfo出力用
var sw = new StreamWriter(path_infocsv, false, System.Text.Encoding.GetEncoding("shift_jis"));
// 出力用csvの準備
sw.Write(
"image" + "," +
"L1" + "," + "a1" + "," + "b1" + "," +
"L2" + "," + "a2" + "," + "b2" + "," +
"L3" + "," + "a3" + "," + "b3" + "," +
"L4" + "," + "a4" + "," + "b4"
);
sw.WriteLine();
sw.Close();
using (MemoryStream ms = new MemoryStream())
{
// ディレクトリglobの取得
var glob_dir = Directory.GetDirectories("input");
for (int a = 0; a < glob_dir.Length; a++)
{
manualReset.WaitOne();
// 画像と校正ファイルのパス
var glob_file = Directory.GetFiles(glob_dir[a]);
var path_calib = glob_file.Where(n => n.Contains("csv")).ToList()[0];
var path_image = glob_file.Where(n => n.Contains("bmp") || n.Contains("png")).ToList()[0];
var path_base = Directory.GetCurrentDirectory();
var name_image = Path.GetFileName(path_image);
var name_dir = Path.GetFileName(glob_dir[a]);
// ステータスの表示
Invoke((MethodInvoker)delegate
{
label_processingFileName.Text = "Processing File: " + "\\" + name_dir;
count = a + 1;
label_totalProgress.Text = "Total Progress: " + count + "/" + glob_dir.Length;
});
// 入力画像読み込み・表示
mat_input = Cv2.ImRead(path_image, ImreadModes.Color);
bitmap_bitch = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(mat_input);
Invoke((MethodInvoker)delegate
{
pictureBox_input.Image = bitmap_bitch;
pictureBox_input.Refresh();
});
// Detection
label8.BackColor = Color.White;
label1.BackColor = Color.Red;
mat_drawBox = mat_input.Clone();
mat_cropped = new Mat(mat_input.Size(), MatType.CV_8UC3, 1);
byte_inputDetection = Bitmap2Byte(bitmap_bitch);
using (var graph = new TFGraph())
{
var model = File.ReadAllBytes(path_base + "/Detection_Normal.pb");
graph.Import(model, "");
using (var session = new TFSession(graph))
{
var tensor = ImageUtil.CreateTensorFromImageFile(byte_inputDetection, TFDataType.UInt8);
var runner = session.GetRunner();
runner
.AddInput(graph["image_tensor"][0], tensor)
.Fetch("detection_boxes", "detection_scores", "detection_classes", "num_detections");
var output = runner.Run();
var boxes = (float[,,])output[0].GetValue();
var scores = (float[,])output[1].GetValue();
var classes = (float[,])output[2].GetValue();
var detections = (float[])output[3].GetValue();
check_detection = 0;
max_score = 0;
for (int i = 0; i < scores.Length; i++)
{
if ((scores[0, i] > 0.5) && (scores[0, i] > max_score))
{
max_score = scores[0, i];
float y_min = boxes[0, i, 0] * (float)bitmap_bitch.Height;
float x_min = boxes[0, i, 1] * (float)bitmap_bitch.Width;
float y_max = boxes[0, i, 2] * (float)bitmap_bitch.Height;
float x_max = boxes[0, i, 3] * (float)bitmap_bitch.Width;
P1.X = (int)x_min;
P1.Y = (int)y_min;
P2.X = (int)x_max;
P2.Y = (int)y_max;
Cv2.Rectangle(mat_drawBox, P1, P2, new Scalar(0, 255, 0), 5);
rectangle.X = (int)x_min;
rectangle.Y = (int)y_min;
rectangle.Width = (int)(x_max - x_min);
rectangle.Height = (int)(y_max - y_min);
check_detection = 1;
}
}
}
}
// Detection結果表示・保存
mat_drawBox.SaveImage(path_base + "\\detection" + "\\" + name_dir + ".bmp");
bitmap_bitch = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(mat_drawBox);
Invoke((MethodInvoker)delegate
{
pictureBox_detection.Image = bitmap_bitch;
pictureBox_detection.Refresh();
});
label1.BackColor = Color.White;
// 舌検出領域でcrop
label2.BackColor = Color.Red;
for (int i = P1.Y; i < P2.Y; i++)
{
for (int j = P1.X; j < P2.X; j++)
{
Vec3b pix = mat_input.At<Vec3b>(i, j);
mat_cropped.Set<Vec3b>(i, j, pix);
}
}
mat_cropped.SaveImage(path_base + "\\cropped" + "\\" + name_dir + ".bmp");
// 舌検出領域でresize
OpenCvSharp.Size size_roi = new OpenCvSharp.Size();
size_roi.Height = rectangle.Height;
size_roi.Width = rectangle.Width;
roi = new Rect(P1, size_roi);
// 20210201
var mat_input2 = mat_input.Clone();
mat_input2 = mat_input2 * 1.5;
mat_roisize = mat_input2.Clone(roi);
Cv2.Resize(mat_roisize, mat_roi, mat_roi256.Size());
mat_roi.SaveImage(path_base + "\\cropresized" + "\\" + name_dir + ".bmp");
bitmap_bitch = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(mat_roi);
Invoke((MethodInvoker)delegate
{
pictureBox_cropResized.Image = bitmap_bitch;
pictureBox_cropResized.Refresh();
});
label2.BackColor = Color.White;
// Segmenation
label3.BackColor = Color.Red;
byte_inputSegmentation = Bitmap2Byte(bitmap_bitch);
Thread.Sleep(1000);
modelFile = DownloadDefaultModel(path_base);
ii = 0;
using (var graph = new TFGraph())
{
var model = File.ReadAllBytes(modelFile);
graph.Import(model, "");
using (var session = new TFSession(graph))
{
var tensor = ImageUtil2.CreateTensorFromImageFile(byte_inputSegmentation);
var runner = session.GetRunner();
runner
//.AddInput(graph["generator/input_image"][0], tensor)
//.Fetch(graph["generator/prediction"][0]);
.AddInput(graph["input_image"][0], tensor)
.Fetch(graph["generator1/decoder_1/Tanh"][0]);
var output = runner.Run();
float[,,,] resultfloat = (float[,,,])output[0].GetValue(jagged: false);
for (int p = 0; p < 256; p++)
{
for (int q = 0; q < 256; q++)
{
float check = resultfloat[0, p, q, 0];
if (check < 0)
{
mask[ii] = 0;
}
else
{
mask[ii] = 255;
}
ii++;
}
}
}
}
GC.Collect();
Thread.Sleep(1000);
// segmentation結果表示・保存
bitmap_bitch = ToGrayBitmap(mask, 256, 256);
mat_output = OpenCvSharp.Extensions.BitmapConverter.ToMat(bitmap_bitch);
bitmap_bitch = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(mat_output);
Invoke((MethodInvoker)delegate
{
pictureBox_output.Image = bitmap_bitch;
pictureBox_output.Refresh();
});
label3.BackColor = Color.White;
label4.BackColor = Color.Red;
mat_output.SaveImage(path_base + "\\output256" + "\\" + name_dir + ".bmp");
// 後処理(領域拡張法)でノイズ除去 iteration 2
try
{
RemoveSmallRegion(path_base + "\\output256" + "\\" + name_dir + ".bmp", path_base + "\\output_changed1" + "\\" + name_dir + ".bmp", 500, 1, 1);
RemoveSmallRegion(path_base + "\\output_changed1" + "\\" + name_dir + ".bmp", path_base + "\\output_changed2" + "\\" + name_dir + ".bmp", 500, 0, 0);
}
catch
{
MessageBox.Show("Error: Unable to reprocess! Please check is there [RemoveSmallRegionDLL.dll] file in floder?", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
break;
}
mat_outputSRG = new Mat(path_base + "\\output_changed2" + "\\" + name_dir + ".bmp", ImreadModes.GrayScale);
bitmap_bitch = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(mat_outputSRG);
Invoke((MethodInvoker)delegate
{
pictureBox_outputSRG.Image = bitmap_bitch;
pictureBox_outputSRG.Refresh();
});
label4.BackColor = Color.White;
label5.BackColor = Color.Red;
// バウンディングボックスのサイズに戻す
Cv2.Resize(mat_outputSRG, mat_outputChanged, mat_roisize.Size());
mat_outputChanged.SaveImage(path_base + "\\output_resized" + "\\" + name_dir + ".bmp"); ;
// 入力と同じサイズでマスクを作成(なんかたまに不安定.resizeで微妙にサイズ変わってrange overかも)
// 気休め
Thread.Sleep(100);
GC.Collect();
mat_mask = new Mat(mat_input.Size(), MatType.CV_8UC1, 0);
var y_mask = 0;
for (int y = P1.Y; y < P2.Y; y++)
{
if (y_mask >= mat_outputChanged.Height)
break;
var x_mask = 0;
for (int x = P1.X; x < P2.X; x++)
{
if (x_mask >= mat_outputChanged.Width)
break;
int pix = mat_outputChanged.At<int>(y_mask, x_mask);
mat_mask.Set<int>(y, x, pix);
x_mask++;
}
y_mask++;
}
mmp = 0;
Cv2.Resize(mat_mask, mat_mask, mat_input.Size());
mat_mask.SaveImage(path_base + "\\mask" + "\\" + name_dir + ".bmp");
// ノイズ処理
try
{
RemoveSmallRegion(path_base + "\\mask" + "\\" + name_dir + ".bmp", path_base + "\\mask_changed1" + "\\" + name_dir + ".bmp", 500, 1, 1);
RemoveSmallRegion(path_base + "\\mask_changed1" + "\\" + name_dir + ".bmp", path_base + "\\mask_changed2" + "\\" + name_dir + ".bmp", 500, 0, 0);
}
catch
{
MessageBox.Show("Error: Unable to reprocess! Please check is there [RemoveSmallRegionDLL.dll] file in floder?", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
break;
}
mat_maskSRG = new Mat(path_base + "\\mask_changed2" + "\\" + name_dir + ".bmp", ImreadModes.GrayScale);
Cv2.Threshold(mat_maskSRG, mat_maskSRG, 128, 255, ThresholdTypes.Binary);
// 2値マスクの最終結果
mat_maskSRG.SaveImage(path_base + "\\mask_final" + "\\" + name_dir + ".bmp");
bitmap_bitch = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(mat_maskSRG);
Invoke((MethodInvoker)delegate
{
pictureBox_maskSRG.Image = bitmap_bitch;
pictureBox_maskSRG.Refresh();
});
label5.BackColor = Color.White;
// 元画像とマスクを合わせて,舌領域を抜き出す
// todo: opencv等によるマスク処理と領域計算へ
label6.BackColor = Color.Red;
mat_extraction = mat_input.Clone();
areaCount = 0;
for (int i = 0; i < mat_input.Height; i++)
{
for (int j = 0; j < mat_input.Width; j++)
{
Vec3b pix = mat_extraction.At<Vec3b>(i, j);
if (mat_maskSRG.At<int>(i, j) == 0)
{
pix[0] = (byte)(255);
pix[1] = (byte)(255);
pix[2] = (byte)(255);
mat_extraction.Set<Vec3b>(i, j, pix);
}
else
{
pix[0] = (byte)(mat_extraction.At<Vec3b>(i, j).Item0);
pix[1] = (byte)(mat_extraction.At<Vec3b>(i, j).Item1);
pix[2] = (byte)(mat_extraction.At<Vec3b>(i, j).Item2);
mat_extraction.Set<Vec3b>(i, j, pix);
areaCount++;
}
}
}
mat_extraction.SaveImage(path_base + "\\extraction" + "\\" + name_dir + ".bmp");
bitmap_bitch = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(mat_extraction);
Invoke((MethodInvoker)delegate
{
pictureBox_extraction.Image = bitmap_bitch;
pictureBox_extraction.Refresh();
});
label6.BackColor = Color.White;
/// 5点クリックによる色抽出処理
var path_colorMatrixXYZ = "xyz.txt";
// 色抽出処理のクラス
ColorExtractor ce = new ColorExtractor();
// マスクされた舌領域画像の作成
Mat mat_finalMask = mat_maskSRG.Clone();
Cv2.ImWrite(path_base + "\\final_mask" + "\\" + name_dir + ".bmp", mat_finalMask);
Mat mat_maskedImg = new Mat();
mat_input.CopyTo(mat_maskedImg, mat_finalMask);
// 5点クリック法(2010石川)
List<OpenCvSharp.Point> list_5points_3 = ce.Get5points(mat_finalMask, ColorExtractor.FivePointMethod.Method3);
// 8領域の取得
List<OpenCvSharp.Point> list_8area_3 = ce.Get8area(list_5points_3);
// 領域の表示
var mat_areaDicision = ce.ShowResult(mat_input.Clone(), list_5points_3, list_8area_3);
// 色抽出
List<OpenCvSharp.Scalar> list_4Bgr = ce.Get4colors(mat_maskedImg, list_8area_3);
// 色変換(RGB->XYZ->Lab)
List<OpenCvSharp.Scalar> list_4Lab = ce.Calc4Lab(list_4Bgr, path_calib, path_colorMatrixXYZ);
// 保存
string CSVfilename = path_base + "\\color" + "\\" + name_dir + ".csv";
FileStream CSV_file = File.Open(CSVfilename, FileMode.OpenOrCreate, FileAccess.Write);
CSV_file.Seek(0, SeekOrigin.Begin);
CSV_file.SetLength(0);
CSV_file.Close();
StreamWriter CSV_data = new StreamWriter(CSVfilename);
CSV_data.WriteLine("Area,R,G,B,L,a,b");
for (int i = 0; i < list_4Bgr.Count(); i++)
{
string str = (i + 1).ToString() + ",";
str +=
list_4Bgr[i].Val2.ToString("0.0000") + "," +
list_4Bgr[i].Val1.ToString("0.0000") + "," +
list_4Bgr[i].Val0.ToString("0.0000") + "," +
list_4Lab[i].Val0.ToString("0.0000") + "," +
list_4Lab[i].Val1.ToString("0.0000") + "," +
list_4Lab[i].Val2.ToString("0.0000");
CSV_data.WriteLine(str);
}
CSV_data.Close();
// 廃棄
GC.Collect();
System.Threading.Thread.Sleep(100);
mat_areaDicision.SaveImage(path_base + "\\autoAreaDecision" + "\\" + name_dir + ".bmp");
bitmap_bitch = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(mat_areaDicision);
Invoke((MethodInvoker)delegate
{
pictureBox_last.Image = bitmap_bitch;
pictureBox_last.Refresh();
});
label7.BackColor = Color.White;
// 処理log
label8.BackColor = Color.Red;
time = DateTime.Now.ToLocalTime().ToString();
File.AppendAllText("Log.txt ", time + " " + "\\" + name_dir + ".bmp" + " Done!\n");
// info出力
sw = new StreamWriter(path_infocsv, true, System.Text.Encoding.GetEncoding("shift_jis"));
string stra = "";
for (int i = 0; i < list_4Bgr.Count(); i++)
{
stra +=
list_4Lab[i].Val0.ToString("0.0000") + "," +
list_4Lab[i].Val1.ToString("0.0000") + "," +
list_4Lab[i].Val2.ToString("0.0000") + ",";
}
sw.Write(
name_dir.ToString() + "," +
stra
);
sw.Write("\n");
sw.Close();
// 破棄
}
GC.Collect();
MessageBox.Show("Finished!");
Invoke((MethodInvoker)delegate
{
button_start.Enabled = true;
button_pause.Enabled = false;
label_processingFileName.Text = "Processing File: None";
});
}
}
// Debugs
private void BackgroundWorker1_DoWork_TIASdata(object sender, DoWorkEventArgs e)
{
// boundingboxなどのinfo出力用
var sw = new StreamWriter(path_infocsv, false, System.Text.Encoding.GetEncoding("shift_jis"));
// 出力用csvの準備
sw.WriteLine(
"image" + "," +
"top left X" + "," + "top left Y" + "," + "bottom right X" + "," + "bottom right Y" + "," +
"Width" + "," + "Height" + "," + "Area");
sw.Close();
// TIASフォルダのパスを取得
var path_procBase = "";
Invoke((MethodInvoker)delegate
{
//ダイアログを表示する
if (folderBrowserDialog1.ShowDialog() == DialogResult.OK)
{
path_procBase = folderBrowserDialog1.SelectedPath;
label_processingFileName.Text = "処理フォルダ: " + path_procBase;
Console.WriteLine("処理フォルダ: " + path_procBase);
}
else
{
MessageBox.Show("プログラムを再起動してください。");
return;
}
});
// 色抽出(TongueAnalysisbin2.3)のため,Proclistを初期化
FileStream fs = File.Open(path_procList, FileMode.OpenOrCreate, FileAccess.Write);
fs.Seek(0, SeekOrigin.Begin);
fs.SetLength(0);
StreamWriter sw_ = new StreamWriter(fs);
sw_.Write("BASEDIR=" + Directory.GetCurrentDirectory() + "\\input");
sw_.WriteLine();
sw_.Close();
fs.Close();
try
{
// inputとoutputフォルダを空にする ToDo: 過去に処理したデータがあれば再利用
var _target = new DirectoryInfo("input");
foreach (FileInfo file in _target.GetFiles())
file.Delete();
foreach (DirectoryInfo dir in _target.GetDirectories())
dir.Delete(true);
_target = new DirectoryInfo("output");
foreach (FileInfo file in _target.GetFiles())
file.Delete();
foreach (DirectoryInfo dir in _target.GetDirectories())
dir.Delete(true);
// 選択されたTIASdirの全日付dir
var glob_tias_dirs = Directory.GetDirectories(path_procBase);
for (int a = 0; a < glob_tias_dirs.Length; a++)
{
// 全日付dirに入っている全dir
var glob_date_dirs = Directory.GetDirectories(glob_tias_dirs[a]);
// 日付dirをコピー
var path_data_dst = @"input\" + Path.GetFileName(glob_tias_dirs[a]);
if (!Directory.Exists(path_data_dst))
{
Directory.CreateDirectory(path_data_dst);
}
else
{
Console.WriteLine(path_data_dst + "は既に存在します");
}
// 画像dirと校正dir
var path_calib_dirs = glob_date_dirs.Where(n => n.Contains("校正")).ToList();
var path_notCalib_dirs = glob_date_dirs.Where(n => !n.Contains("校正")).ToList();
var path_img_dirs = path_notCalib_dirs.Where(n => File.Exists(n + @"\Shot0001.bmp")).ToList();
// yyyy-MM-dd
var st_time_tiasDir = Path.GetFileName(glob_tias_dirs[a]).ToString();
// 色抽出(TongueAnalysisbin2.3)のため,Proclistを記述
sw_ = new StreamWriter(path_procList, true);
sw_.WriteLine(st_time_tiasDir);
sw_.Close();
// 画像dirに対して処理
for (int b = 0; b < path_img_dirs.Count(); b++)
{
Console.WriteLine("img dir:");
Console.WriteLine(path_img_dirs[b]);
// もし舌裏撮影なら飛ばす
if (File.Exists(path_img_dirs[b] + @"\NShot0001.bmp"))
continue;
// もし舌画像がなければ飛ばす
if (!File.Exists(path_img_dirs[b] + @"\Shot0001.bmp"))
continue;
// HH_mm_ss-患者ID-来院回数
var st_time_imgDir = Path.GetFileName(path_img_dirs[b]).ToString().Substring(0, 8);
Console.WriteLine(st_time_imgDir);
// 日付時刻文字列をDatetimeフォーマットへ変換
string strTime = st_time_tiasDir + "-" + st_time_imgDir;
string format = "yyyy-MM-dd-HH_mm_ss";
DateTime time_img_dir = DateTime.ParseExact(strTime, format, null);
// 舌画像dirから見て最新calib_dirを探索
var path_newCalibDir = path_calib_dirs[0];
foreach (var path_calibDir in path_calib_dirs)
{
string target = st_time_tiasDir + "-" + Path.GetFileName(path_calibDir).ToString().Substring(0, 8);
DateTime time_target = DateTime.ParseExact(target, format, null);
string newone = st_time_tiasDir + "-" + Path.GetFileName(path_newCalibDir).ToString().Substring(0, 8);
DateTime time_newone = DateTime.ParseExact(newone, format, null);
// imgDirより前に作成され,かつその中で最新
if (time_img_dir > time_target)
if (time_newone < time_target)
path_newCalibDir = path_calibDir;
}
Console.WriteLine("入力画像dir");
Console.WriteLine(path_img_dirs[b]);
Console.WriteLine("入力校正dir");
Console.WriteLine(path_newCalibDir);
// それぞれのファイルとフォルダーをコピー
// (条件 処理が二回目以降でinfo.csvが既に存在するなら,info.csvを生成しない)
const string DEFAULT_FILENAME = "Shot0001.bmp";
var path_imgdir_dst = path_data_dst + "\\" + Path.GetFileName(path_img_dirs[b]);
if (!Directory.Exists(path_imgdir_dst))
{
Directory.CreateDirectory(path_imgdir_dst);
File.Copy(path_img_dirs[b] + "\\" + DEFAULT_FILENAME, path_imgdir_dst + "\\" + DEFAULT_FILENAME);
}
else
{
Console.WriteLine(path_imgdir_dst + "は存在します");
}
var path_calibdir_dst = path_data_dst + "\\" + Path.GetFileName(path_newCalibDir);
if (!Directory.Exists(path_calibdir_dst))
{
Directory.CreateDirectory(path_calibdir_dst);
File.Copy(path_newCalibDir + "\\" + DEFAULT_FILENAME, path_calibdir_dst + "\\" + DEFAULT_FILENAME);
}
else
{
Console.WriteLine(path_imgdir_dst + "は存在します");
}
}
}
GC.Collect();
}
catch
{
Console.WriteLine("フォルダの読み込み,校正ファイルの検索における例外");
MessageBox.Show("選択されたフォルダはTIASデータフォルダではありません\nプログラムを再起動してください。");
return;
}
using (MemoryStream ms = new MemoryStream())
{
// ディレクトリglobの取得
var glob_tias_dirs_ = Directory.GetDirectories("input");
for (int a = 0; a < glob_tias_dirs_.Length; a++)
{
// tiasDirに入っている全dir
var glob_date_dirs = Directory.GetDirectories(glob_tias_dirs_[a]);
// 画像dirと校正dir
var path_calib_dirs = glob_date_dirs.Where(n => n.Contains("校正")).ToList();
var path_img_dirs = glob_date_dirs.Where(n => !n.Contains("校正")).ToList();
// yyyy-MM-dd
var st_time_tiasDir = Path.GetFileName(glob_tias_dirs_[a]).ToString();
Console.WriteLine(st_time_tiasDir.ToString());
// 画像dir
for (int b = 0; b < path_img_dirs.Count(); b++)
{
Console.WriteLine(path_img_dirs.Count());
Console.WriteLine(path_img_dirs[b]);
// HH_mm_ss-患者ID-来院回数
var st_time_imgDir = Path.GetFileName(path_img_dirs[b]).ToString().Substring(0, 8);
Console.WriteLine(st_time_imgDir);
// 日付時刻文字列をDatetimeフォーマットへ変換
string strTime = st_time_tiasDir + "-" + st_time_imgDir;
string format = "yyyy-MM-dd-HH_mm_ss";
DateTime time_img_dir = DateTime.ParseExact(strTime, format, null);
// 舌画像dirから見て最新calib_dirを探索
var path_newCalibDir = path_calib_dirs[0];
foreach (var path_calibDir in path_calib_dirs)
{
string target = st_time_tiasDir + "-" + Path.GetFileName(path_calibDir).ToString().Substring(0, 8);
DateTime time_target = DateTime.ParseExact(target, format, null);
string newone = st_time_tiasDir + "-" + Path.GetFileName(path_newCalibDir).ToString().Substring(0, 8);
DateTime time_newone = DateTime.ParseExact(newone, format, null);
// imgDirより前に作成され,かつその中で最新
if (time_img_dir > time_target)
if (time_newone < time_target)
path_newCalibDir = path_calibDir;
}
Console.WriteLine("入力画像dir");
Console.WriteLine(path_img_dirs[b]);
Console.WriteLine("入力校正dir");
Console.WriteLine(path_newCalibDir);
// 画像に対する繰り返し(今は最も古い画像(0001.bmp)のみを処理,ゆくゆくは全画像(0001-0200)を処理)
var glob_image_path = Directory.GetFiles(path_img_dirs[b]).Where(n => n.Contains(".bmp")); ;
foreach (var path_img in glob_image_path)
{
// DeepTIAS処理
manualReset.WaitOne();
// 画像と校正ファイルのパス
var path_calib = Directory.GetFiles(path_newCalibDir).Where(n => n.Contains("Shot0001.bmp")).ToList()[0];
var path_base = Directory.GetCurrentDirectory();
var name_image = Path.GetFileName(path_img);
var name_dir = Path.GetFileName(st_time_tiasDir);
// ステータスの表示
Invoke((MethodInvoker)delegate
{
label_processingFileName.Text = "Processing File: " + name_dir + "\\" + Path.GetFileName(path_img_dirs[b]);
count = a + 1;
label_totalProgress.Text = "Total Progress: " + count + "/" + glob_tias_dirs_.Length;
});
// 入力画像読み込み・表示
mat_input = Cv2.ImRead(path_img, ImreadModes.Color);
bitmap_bitch = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(mat_input);
Invoke((MethodInvoker)delegate
{
pictureBox_input.Image = bitmap_bitch;
pictureBox_input.Refresh();
});
// Detection
label8.BackColor = Color.White;
label1.BackColor = Color.Red;
mat_drawBox = mat_input.Clone();
mat_cropped = new Mat(mat_input.Size(), MatType.CV_8UC3, 1);
byte_inputDetection = Bitmap2Byte(bitmap_bitch);
using (var graph = new TFGraph())
{
var model = File.ReadAllBytes(path_base + "/Detection_Normal.pb");
graph.Import(model, "");
using (var session = new TFSession(graph))
{
var tensor = ImageUtil.CreateTensorFromImageFile(byte_inputDetection, TFDataType.UInt8);
var runner = session.GetRunner();
runner
.AddInput(graph["image_tensor"][0], tensor)
.Fetch("detection_boxes", "detection_scores", "detection_classes", "num_detections");
var output = runner.Run();
var boxes = (float[,,])output[0].GetValue();
var scores = (float[,])output[1].GetValue();
var classes = (float[,])output[2].GetValue();
var detections = (float[])output[3].GetValue();
check_detection = 0;
max_score = 0;
for (int i = 0; i < scores.Length; i++)
{
if ((scores[0, i] > 0.5) && (scores[0, i] > max_score))
{
max_score = scores[0, i];
float y_min = boxes[0, i, 0] * (float)bitmap_bitch.Height;
float x_min = boxes[0, i, 1] * (float)bitmap_bitch.Width;
float y_max = boxes[0, i, 2] * (float)bitmap_bitch.Height;
float x_max = boxes[0, i, 3] * (float)bitmap_bitch.Width;
P1.X = (int)x_min;
P1.Y = (int)y_min;
P2.X = (int)x_max;
P2.Y = (int)y_max;
Cv2.Rectangle(mat_drawBox, P1, P2, new Scalar(0, 255, 0), 5);
rectangle.X = (int)x_min;
rectangle.Y = (int)y_min;
rectangle.Width = (int)(x_max - x_min);
rectangle.Height = (int)(y_max - y_min);
check_detection = 1;
}
}
}
}
// Detection結果表示・保存
mat_drawBox.SaveImage(path_base + "\\detection" + "\\" + name_dir + ".bmp");
bitmap_bitch = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(mat_drawBox);
Invoke((MethodInvoker)delegate
{
pictureBox_detection.Image = bitmap_bitch;
pictureBox_detection.Refresh();
});
label1.BackColor = Color.White;
// 舌検出領域でcrop
label2.BackColor = Color.Red;
for (int i = P1.Y; i < P2.Y; i++)
{
for (int j = P1.X; j < P2.X; j++)
{
Vec3b pix = mat_input.At<Vec3b>(i, j);
mat_cropped.Set<Vec3b>(i, j, pix);
}
}
mat_cropped.SaveImage(path_base + "\\cropped" + "\\" + name_dir + ".bmp");
// 舌検出領域でresize
OpenCvSharp.Size size_roi = new OpenCvSharp.Size();
size_roi.Height = rectangle.Height;
size_roi.Width = rectangle.Width;
roi = new Rect(P1, size_roi);
// 20210201
//var mat_input2 = mat_input.Clone();
//mat_input2 = mat_input2 * 1.5;
mat_roisize = mat_input.Clone(roi);
Cv2.Resize(mat_roisize, mat_roi, mat_roi256.Size());
mat_roi.SaveImage(path_base + "\\cropresized" + "\\" + name_dir + ".bmp");
bitmap_bitch = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(mat_roi);
Invoke((MethodInvoker)delegate
{
pictureBox_cropResized.Image = bitmap_bitch;
pictureBox_cropResized.Refresh();
});
label2.BackColor = Color.White;
// Segmenation
label3.BackColor = Color.Red;
byte_inputSegmentation = Bitmap2Byte(bitmap_bitch);
Thread.Sleep(1000);
modelFile = DownloadDefaultModel(path_base);
ii = 0;
using (var graph = new TFGraph())
{
var model = File.ReadAllBytes(modelFile);
graph.Import(model, "");
using (var session = new TFSession(graph))
{
var tensor = ImageUtil2.CreateTensorFromImageFile(byte_inputSegmentation);
var runner = session.GetRunner();
runner
//.AddInput(graph["generator/input_image"][0], tensor)
//.Fetch(graph["generator/prediction"][0]);
.AddInput(graph["input_image"][0], tensor)
.Fetch(graph["generator1/decoder_1/Tanh"][0]);
var output = runner.Run();
float[,,,] resultfloat = (float[,,,])output[0].GetValue(jagged: false);
for (int p = 0; p < 256; p++)
{
for (int q = 0; q < 256; q++)
{
float check = resultfloat[0, p, q, 0];
if (check < 0)
{
mask[ii] = 0;
}
else
{
mask[ii] = 255;
}
ii++;
}
}
}
}
GC.Collect();
Thread.Sleep(1000);
// segmentation結果表示・保存
bitmap_bitch = ToGrayBitmap(mask, 256, 256);
mat_output = OpenCvSharp.Extensions.BitmapConverter.ToMat(bitmap_bitch);
bitmap_bitch = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(mat_output);
Invoke((MethodInvoker)delegate
{
pictureBox_output.Image = bitmap_bitch;
pictureBox_output.Refresh();
});
label3.BackColor = Color.White;
label4.BackColor = Color.Red;
mat_output.SaveImage(path_base + "\\output256" + "\\" + name_dir + ".bmp");
// 後処理(領域拡張法)でノイズ除去 iteration 2
try
{
RemoveSmallRegion(path_base + "\\output256" + "\\" + name_dir + ".bmp", path_base + "\\output_changed1" + "\\" + name_dir + ".bmp", 500, 1, 1);
RemoveSmallRegion(path_base + "\\output_changed1" + "\\" + name_dir + ".bmp", path_base + "\\output_changed2" + "\\" + name_dir + ".bmp", 500, 0, 0);
}
catch
{
MessageBox.Show("Error: Unable to reprocess! Please check is there [RemoveSmallRegionDLL.dll] file in floder?", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
break;
}
mat_outputSRG = new Mat(path_base + "\\output_changed2" + "\\" + name_dir + ".bmp", ImreadModes.GrayScale);
bitmap_bitch = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(mat_outputSRG);
Invoke((MethodInvoker)delegate
{
pictureBox_outputSRG.Image = bitmap_bitch;
pictureBox_outputSRG.Refresh();
});
label4.BackColor = Color.White;
label5.BackColor = Color.Red;
// バウンディングボックスのサイズに戻す
Cv2.Resize(mat_outputSRG, mat_outputChanged, mat_roisize.Size());
mat_outputChanged.SaveImage(path_base + "\\output_resized" + "\\" + name_dir + ".bmp");
// 入力と同じサイズでマスクを作成(なんかたまに不安定.resizeで微妙にサイズ変わってrange overかも)
// 気休め
Thread.Sleep(100);
GC.Collect();
mat_mask = new Mat(mat_input.Size(), MatType.CV_8UC1, 0);
var y_mask = 0;
for (int y = P1.Y; y < P2.Y; y++)
{
if (y_mask >= mat_outputChanged.Height)
break;
var x_mask = 0;
for (int x = P1.X; x < P2.X; x++)
{
if (x_mask >= mat_outputChanged.Width)
break;
int pix = mat_outputChanged.At<int>(y_mask, x_mask);
mat_mask.Set<int>(y, x, pix);
x_mask++;
}
y_mask++;
}
mmp = 0;
Cv2.Resize(mat_mask, mat_mask, mat_input.Size());
mat_mask.SaveImage(path_base + "\\mask" + "\\" + name_dir + ".bmp");
// ノイズ処理
try
{
RemoveSmallRegion(path_base + "\\mask" + "\\" + name_dir + ".bmp", path_base + "\\mask_changed1" + "\\" + name_dir + ".bmp", 500, 1, 1);
RemoveSmallRegion(path_base + "\\mask_changed1" + "\\" + name_dir + ".bmp", path_base + "\\mask_changed2" + "\\" + name_dir + ".bmp", 500, 0, 0);
}
catch
{
MessageBox.Show("Error: Unable to reprocess! Please check is there [RemoveSmallRegionDLL.dll] file in floder?", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
break;
}
mat_maskSRG = new Mat(path_base + "\\mask_changed2" + "\\" + name_dir + ".bmp", ImreadModes.GrayScale);
Cv2.Threshold(mat_maskSRG, mat_maskSRG, 128, 255, ThresholdTypes.Binary);
// 2値マスクの最終結果
mat_maskSRG.SaveImage(path_base + "\\mask_final" + "\\" + name_dir + ".bmp");
bitmap_bitch = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(mat_maskSRG);
Invoke((MethodInvoker)delegate
{
pictureBox_maskSRG.Image = bitmap_bitch;
pictureBox_maskSRG.Refresh();
});
label5.BackColor = Color.White;
// 元画像とマスクを合わせて,舌領域を抜き出す
// todo: opencv等によるマスク処理と領域計算へ
label6.BackColor = Color.Red;
mat_extraction = mat_input.Clone();
areaCount = 0;
for (int i = 0; i < mat_input.Height; i++)
{
for (int j = 0; j < mat_input.Width; j++)
{
Vec3b pix = mat_extraction.At<Vec3b>(i, j);
if (mat_maskSRG.At<int>(i, j) == 0)
{
pix[0] = (byte)(255);
pix[1] = (byte)(255);
pix[2] = (byte)(255);
mat_extraction.Set<Vec3b>(i, j, pix);
}
else
{
pix[0] = (byte)(mat_extraction.At<Vec3b>(i, j).Item0);
pix[1] = (byte)(mat_extraction.At<Vec3b>(i, j).Item1);
pix[2] = (byte)(mat_extraction.At<Vec3b>(i, j).Item2);
mat_extraction.Set<Vec3b>(i, j, pix);
areaCount++;
}
}
}
mat_extraction.SaveImage(path_base + "\\extraction" + "\\" + name_dir + ".bmp");
bitmap_bitch = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(mat_extraction);
Invoke((MethodInvoker)delegate
{
pictureBox_extraction.Image = bitmap_bitch;
pictureBox_extraction.Refresh();
});
label6.BackColor = Color.White;
/// 5点クリックによる色抽出処理
var path_colorMatrixXYZ = "xyz.txt";
// 色抽出処理のクラス
ColorExtractor ce = new ColorExtractor();
// マスクされた舌領域画像の作成
Mat mat_finalMask = mat_maskSRG.Clone();
Cv2.ImWrite(path_base + "\\final_mask" + "\\" + name_dir + ".bmp", mat_finalMask);
Mat mat_maskedImg = new Mat();
mat_input.CopyTo(mat_maskedImg, mat_finalMask);
// 5点クリック法(2010石川)
List<OpenCvSharp.Point> list_5points_3 = ce.Get5points(mat_finalMask, ColorExtractor.FivePointMethod.Method3);
// 5点座標を入力画像,校正画像と同じディレクトリに保存
var path_infocsv = path_img_dirs[b] + "\\Info.csv";
FileStream CSV_file = File.Open(path_infocsv, FileMode.OpenOrCreate, FileAccess.Write);
CSV_file.Seek(0, SeekOrigin.Begin);
CSV_file.SetLength(0);
CSV_file.Close();
Console.WriteLine(path_infocsv);
StreamWriter CSV_data = new StreamWriter(path_infocsv);
CSV_data.WriteLine(Path.GetFileName(path_img));
foreach (var item in list_5points_3)
{
string str = item.X + "," + item.Y;
CSV_data.WriteLine(str);
}
CSV_data.Close();
// 8領域の取得
List<OpenCvSharp.Point> list_8area_3 = ce.Get8area(list_5points_3);
// 領域の表示
var mat_areaDicision = ce.ShowResult(mat_input.Clone(), list_5points_3, list_8area_3);
mat_areaDicision.SaveImage(path_base + "\\autoAreaDecision" + "\\" + name_dir + ".bmp");
bitmap_bitch = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(mat_areaDicision);
Invoke((MethodInvoker)delegate
{
pictureBox_last.Image = bitmap_bitch;
pictureBox_last.Refresh();
});
label7.BackColor = Color.White;
//csvにboundingbox情報を保存
sw = new StreamWriter(this.path_infocsv, true, System.Text.Encoding.GetEncoding("shift_jis"));
sw.WriteLine(
path_img.Substring(6) + ","
+ P1.X.ToString() + "," + P1.Y.ToString() + ","
+ P2.X.ToString() + "," + P2.Y.ToString() + ","
+ Math.Abs(P1.X - P2.X).ToString() + "," + Math.Abs(P1.Y - P2.Y).ToString() + ","
+ areaCount.ToString()
);
sw.Close();
// 処理log
label8.BackColor = Color.Red;
time = DateTime.Now.ToLocalTime().ToString();
File.AppendAllText("Log.txt ", time + " " + "\\" + name_dir + ".bmp" + " Done!\n");
Thread.Sleep(100);
// 破棄
GC.Collect();
}
}
}
// 色抽出のためproclist
sw_ = new StreamWriter(path_procList, true);
sw_.WriteLine("END");
sw_.Close();
// 最後の日付のデータを監視し,更新され次第,tongueanalysisを閉じる
var fs2 = File.Open(path_procList, FileMode.Open, FileAccess.Read);
var sr = new StreamReader(fs2);
fs2.Seek(0, SeekOrigin.Begin);
string line = "";
string line_l = "";
var path_watchedFile = "";
while ((line = sr.ReadLine()) != null)
{
if (line != "END")
{
line_l = line;
continue;
}
Console.WriteLine("Last folder:");
var path_watchedFolder = Directory.GetCurrentDirectory() + "\\input\\" + line_l;
var path_img_dirs = Directory.GetDirectories(path_watchedFolder).Where(n => !n.Contains("校正")).ToList();
path_watchedFolder = path_img_dirs[path_img_dirs.Count() - 1];
path_watchedFile = path_watchedFolder + "\\" + "analysis.csv";
Console.WriteLine("Watching:" + path_watchedFile);
}
sr.Close();
fs2.Close();
// proclist最後のファイルについて,analysis.csvの更新を非同期監視
System.IO.FileSystemWatcher watcher = new System.IO.FileSystemWatcher();
watcher.Path = Path.GetDirectoryName(path_watchedFile);
watcher.NotifyFilter = (System.IO.NotifyFilters.LastAccess
| System.IO.NotifyFilters.LastWrite
| System.IO.NotifyFilters.FileName
| System.IO.NotifyFilters.DirectoryName);
watcher.Filter = "analysis.csv";
//UIのスレッドにマーシャリングする
//コンソールアプリケーションでの使用では必要ない
watcher.SynchronizingObject = this;
//イベントハンドラの追加
watcher.Changed += new System.IO.FileSystemEventHandler(watcher_Changed);
watcher.Created += new System.IO.FileSystemEventHandler(watcher_Changed);
watcher.Deleted += new System.IO.FileSystemEventHandler(watcher_Changed);
watcher.Renamed += new System.IO.RenamedEventHandler(watcher_Renamed);
//監視を開始する
watcher.EnableRaisingEvents = true;
Console.WriteLine("監視を開始しました。");
// TongueAnalysis_bin2.3を動かす
var proc = Process.Start(@"TongueAnalysis_bin2.3\TongueAnalysis.exe");
while(true)
{
if (IsLastFileChanged)
{
watcher.EnableRaisingEvents = false;
watcher.Dispose();
proc.Kill();
break;
}
else
{
proc.WaitForExit(100);
}
}
// 生成されたファイルをわかりやすい場所(exeの親dir)にコピー
var path_finaloutputDir = @"..\Output";
if (!Directory.Exists(path_finaloutputDir))
Directory.CreateDirectory(path_finaloutputDir);
else
{
Console.WriteLine(path_finaloutputDir + "は既に存在します");
Directory.Delete(path_finaloutputDir, true);
Directory.CreateDirectory(path_finaloutputDir);
}
var _target = new DirectoryInfo("output");
foreach (FileInfo file in _target.GetFiles())
{
if (file.Name != "analysis.csv")
file.CopyTo(path_finaloutputDir + @"\" + file.Name);
}
// 形状に関する出力csvと色に関するcsvを合わせる
var path_infocsv_ = path_infocsv;
var path_colorcsv_ = @"output\analysis.csv";
var path_result_ = path_finaloutputDir + @"\AnalysisResult.csv";
var isFirst = true;
using (var sr_info = new StreamReader(path_infocsv_))
using (var sr_color = new StreamReader(path_colorcsv_))
using (var sw_result = new StreamWriter(path_result_))
{
while ((sr_info.EndOfStream == false) && (sr_color.EndOfStream == false))
{
string line_info = sr_info.ReadLine();
line_info = line_info.Substring(line_info.IndexOf(",") + 1);
Console.WriteLine(line_info);
string line_color = sr_color.ReadLine();
Console.WriteLine(line_color);
string line_result = line_color + line_info;
if (isFirst)
{
var header =
"date,time-case,image,L1,a1,b1,L2,a2,b2,L3,a3,b3,L4,a4,b4," +
"top left X,top left Y,bottom right X,bottom right Y,Width,Height,Area";
sw_result.WriteLine(header);
isFirst = false;
continue;
}
sw_result.WriteLine(line_result);
}
sw_result.Close();
sr_info.Close();
sr_color.Close();
}
// 終了処理
GC.Collect();
MessageBox.Show("Finished!");
Invoke((MethodInvoker)delegate
{
button_start.Enabled = true;
button_pause.Enabled = false;
label_processingFileName.Text = "Processing File: None";
});
}
}
//イベントハンドラ
private void watcher_Changed(System.Object source,
System.IO.FileSystemEventArgs e)
{
switch (e.ChangeType)
{
case System.IO.WatcherChangeTypes.Changed:
Console.WriteLine(
"ファイル 「" + e.FullPath + "」が変更されました。");
IsLastFileChanged = true;
break;
case System.IO.WatcherChangeTypes.Created:
Console.WriteLine(
"ファイル 「" + e.FullPath + "」が作成されました。");
break;
case System.IO.WatcherChangeTypes.Deleted:
Console.WriteLine(
"ファイル 「" + e.FullPath + "」が削除されました。");
break;
}
}
private void watcher_Renamed(System.Object source,
System.IO.RenamedEventArgs e)
{
Console.WriteLine(
"ファイル 「" + e.FullPath + "」の名前が変更されました。");
}
private void Button_pause_Click(object sender, EventArgs e)
{
if (button_pause.Text == "Pause")
{
manualReset.Reset();
button_pause.Text = "Continue";
}
else
{
manualReset.Set();
button_pause.Text = "Pause";
}
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
}
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
}
}
}