Selects ROI in images from a folder. Perfect for automating the creation of image data sets
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Program.cs 7.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327
  1. using System;
  2. using System.Drawing;
  3. using System.Windows.Forms;
  4. using System.IO;
  5. using Newtonsoft.Json;
  6. using System.Linq;
  7. using System.Collections.Generic;
  8. public class HelloWorld : Form
  9. {
  10. [STAThread]
  11. static public void Main ()
  12. {
  13. Application.Run (new HelloWorld ());
  14. }
  15. string selectedPath;
  16. RegisteredImage[] rimages;
  17. int currentIdx = 0;
  18. List<Selection> currenSelections = new List<Selection>();
  19. Label lblNImages = new Label ();
  20. DB db = new DB();
  21. bool dragging = false;
  22. public HelloWorld ()
  23. {
  24. this.DoubleBuffered = true;
  25. this.KeyPreview = true;
  26. EventHandler HGoFirst = (s, ev) => {GoFirst();};
  27. EventHandler HNonEdited = (s, ev) => {NonEdited();};
  28. EventHandler HNext = (s, ev) => {Next();};
  29. EventHandler HPrevious = (s, ev) => {Previous();};
  30. EventHandler HClear = (s, ev) => {Clear();};
  31. EventHandler HUndo = (s, ev) => {Undo();};
  32. this.KeyDown += (s, e) => {
  33. e.Handled = true;
  34. if (e.KeyCode == Keys.NumPad0 || e.KeyCode == Keys.D0) {
  35. GoFirst();
  36. } else if (e.KeyCode == Keys.D1 || e.KeyCode == Keys.NumPad1) {
  37. NonEdited();
  38. } else if (e.KeyCode == Keys.P) {
  39. Next();
  40. } else if (e.KeyCode == Keys.O) {
  41. Previous();
  42. } else if (e.KeyCode == Keys.Escape) {
  43. Clear();
  44. } else if (e.KeyCode == Keys.Back) {
  45. Undo();
  46. }
  47. };
  48. int x = this.AddButton("First", HGoFirst, 0);
  49. x = this.AddButton("First Non-Edited", HNonEdited, x+1);
  50. x = this.AddButton("Next", HNext, x+1);
  51. x = this.AddButton("Previous", HPrevious, x+1);
  52. x = this.AddButton("Clear", HClear, x+1);
  53. x = this.AddButton("Undo", HUndo, x+1);
  54. Label lbl = new Label ();
  55. lbl.Text = "First: 0, First non-edited: 1, Next: P, Previous: O, Clear: Escape, Undo: Backspace";
  56. lbl.Location = new Point (x, 0);
  57. lbl.BackColor = Color.Black;
  58. lbl.ForeColor = Color.Red;
  59. lbl.Width = 1000;
  60. this.Controls.Add (lbl);
  61. lblNImages.Location = new Point (x, 20);
  62. lblNImages.BackColor = Color.Black;
  63. lblNImages.ForeColor = Color.Red;
  64. lblNImages.Width = 1000;
  65. this.Controls.Add (lblNImages);
  66. this.Cursor = Cursors.Cross;
  67. }
  68. void SetNumberImagesLabel() {
  69. this.lblNImages.Text = "Current cuts: " + this.currenSelections.Count ().ToString ();
  70. }
  71. int AddButton (string text, EventHandler e, int positionX)
  72. {
  73. Button b = new Button ();
  74. b.Text = text;
  75. b.Click += e;
  76. b.Location = new Point (positionX, 0);
  77. b.Cursor = Cursors.Arrow;
  78. Controls.Add (b);
  79. return positionX + b.Width;
  80. }
  81. void Save ()
  82. {
  83. this.rimages [this.currentIdx].Selections = this.currenSelections;
  84. this.rimages [this.currentIdx].Registered = true;
  85. this.db.Save (this.selectedPath);
  86. }
  87. void TestCurrentIndex () {
  88. if (this.currentIdx == this.rimages.Count())
  89. this.currentIdx = 0;
  90. if (this.currentIdx == -1)
  91. this.currentIdx = this.rimages.Count() - 1;
  92. }
  93. void GoFirst ()
  94. {
  95. this.Save ();
  96. currentIdx = 0;
  97. this.currenSelections = this.rimages [this.currentIdx].Selections;
  98. Refresh ();
  99. }
  100. void NonEdited ()
  101. {
  102. this.Save ();
  103. for (int i = 0; i < this.rimages.Count(); i++) {
  104. if (!this.rimages [i].Registered) {
  105. this.currentIdx = i;
  106. break;
  107. }
  108. }
  109. this.currenSelections = this.rimages [this.currentIdx].Selections;
  110. Refresh();
  111. }
  112. void Next()
  113. {
  114. this.Save ();
  115. currentIdx++;
  116. this.TestCurrentIndex ();
  117. this.currenSelections = this.rimages [this.currentIdx].Selections;
  118. Refresh();
  119. }
  120. void Previous ()
  121. {
  122. this.Save ();
  123. currentIdx--;
  124. this.TestCurrentIndex ();
  125. this.currenSelections = this.rimages [this.currentIdx].Selections;
  126. Refresh();
  127. }
  128. void Clear ()
  129. {
  130. currenSelections = new List<Selection>();
  131. this.Save ();
  132. Refresh();
  133. }
  134. void Undo ()
  135. {
  136. if (currenSelections.Count == 0)
  137. return;
  138. currenSelections = currenSelections.GetRange(0, currenSelections.Count-1);
  139. Refresh();
  140. this.Save ();
  141. }
  142. protected override void OnLoad (EventArgs e)
  143. {
  144. base.OnLoad (e);
  145. var dialog = new FolderBrowserDialog ();
  146. dialog.ShowDialog ();
  147. this.selectedPath = dialog.SelectedPath;
  148. if (String.IsNullOrEmpty (this.selectedPath))
  149. Application.Exit ();
  150. db.Load (this.selectedPath);
  151. foreach (string file in Directory.EnumerateFiles(this.selectedPath, "*.*", SearchOption.AllDirectories))
  152. {
  153. if ((!file.EndsWith (".jpg")) && (!file.EndsWith (".png")) && (!file.EndsWith (".bmp")) && (!file.EndsWith (".gif")))
  154. continue;
  155. var name = file.Substring (this.selectedPath.Length+1);
  156. var files = from x in db.Images where x.Path.Equals(name) select x;
  157. if (files.Count() == 0) {
  158. db.Images.Add (new RegisteredImage {
  159. Path = name,
  160. Registered = false
  161. });
  162. }
  163. }
  164. db.Save (this.selectedPath);
  165. this.rimages = (from x in db.Images where File.Exists(Path.Combine(this.selectedPath, x.Path)) select x).ToArray ();
  166. this.SetNumberImagesLabel ();
  167. this.currenSelections = this.rimages [this.currentIdx].Selections;
  168. this.Refresh ();
  169. }
  170. protected override void OnPaint (PaintEventArgs e)
  171. {
  172. base.OnPaint (e);
  173. if ((this.rimages == null) || (this.rimages.Count() == 0))
  174. return;
  175. this.SetNumberImagesLabel ();
  176. RegisteredImage img = this.rimages [this.currentIdx];
  177. e.Graphics.DrawImageUnscaled (Bitmap.FromFile (Path.Combine (this.selectedPath, img.Path)), new Rectangle (0, 0, this.Width, this.Height));
  178. using (var pen = new Pen(Color.Gold, 3)) {
  179. foreach (var s in this.currenSelections) {
  180. int x = s.X;
  181. int y = s.Y;
  182. int w = s.Width;
  183. int h = s.Height;
  184. if (w < 0) {
  185. x = x + w;
  186. w = Math.Abs (w);
  187. }
  188. if (h < 0) {
  189. y = y + h;
  190. h = Math.Abs (h);
  191. }
  192. e.Graphics.DrawRectangle (pen, x, y, w, h);
  193. }
  194. }
  195. }
  196. protected override void OnResizeEnd (EventArgs e)
  197. {
  198. base.OnResizeEnd (e);
  199. this.Refresh ();
  200. }
  201. protected override void OnMouseDown (MouseEventArgs e)
  202. {
  203. base.OnMouseDown (e);
  204. this.currenSelections.Add (new Selection {
  205. X= e.X,
  206. Y = e.Y,
  207. Width = 0,
  208. Height = 0
  209. });
  210. this.dragging = true;
  211. }
  212. protected override void OnMouseMove (MouseEventArgs e)
  213. {
  214. base.OnMouseMove (e);
  215. if (!dragging)
  216. return;
  217. Selection s = this.currenSelections.Last ();
  218. s.Width = e.X - s.X;
  219. s.Height = e.Y - s.Y;
  220. this.Refresh ();
  221. }
  222. protected override void OnMouseUp (MouseEventArgs e)
  223. {
  224. if (!dragging)
  225. return;
  226. base.OnMouseUp (e);
  227. Selection s = this.currenSelections.Last ();
  228. s.Width = e.X - s.X;
  229. s.Height = e.Y - s.Y;
  230. if ((Math.Abs (s.Width) < 5) && (Math.Abs (s.Height) < 5)) {
  231. currenSelections = currenSelections.GetRange (0, currenSelections.Count - 1);
  232. }
  233. if (s.Width < 0) {
  234. s.X = s.X + s.Width;
  235. s.Width = Math.Abs (s.Width);
  236. }
  237. if (s.Height < 0) {
  238. s.Y = s.Y + s.Height;
  239. s.Height = Math.Abs (s.Height);
  240. }
  241. this.Refresh ();
  242. this.dragging = false;
  243. }
  244. }
  245. class DB
  246. {
  247. public List<RegisteredImage> Images;
  248. const string path = "db.json";
  249. public void Load (string rootPath)
  250. {
  251. string _path = Path.Combine (rootPath, DB.path);
  252. string json = (File.Exists (_path)) ? File.ReadAllText (_path) : "{}";
  253. DB tmp = JsonConvert.DeserializeObject<DB>(json);
  254. this.Images = (tmp.Images == null) ? new List<RegisteredImage>() : tmp.Images;
  255. }
  256. public void Save(string rootPath)
  257. {
  258. string _path = Path.Combine (rootPath, DB.path);
  259. string json = JsonConvert.SerializeObject(this);
  260. File.WriteAllText (_path, json);
  261. }
  262. }
  263. class Selection
  264. {
  265. public int X { get; set; }
  266. public int Y { get; set; }
  267. public int Width { get; set; }
  268. public int Height { get; set; }
  269. }
  270. class RegisteredImage
  271. {
  272. public string Path { get; set; }
  273. public bool Registered { get; set; }
  274. public List<Selection> Selections = new List<Selection>();
  275. }