1 using System;
2 using System.IO;
3 using System.Collections.Generic;
4 using System.ComponentModel;
5 using System.Data;
6 using System.Drawing;
7 using System.Linq;
8 using System.Text;
9 using System.Threading.Tasks;
10 using System.Windows.Forms;
11 using System.Xml;
12
13 namespace Image_mark
14 {
15
16 public partial class Form1 : Form
17 {
18 // 我设置的全局变量
19 private List<string> all_picture_path;
20 private List<string> all_picture_name;
21 private string current_picture_path;
22 private int current_picture_index; // 从1开始
23
24 private int function_select;
25 private const int BROW = 1;
26 private const int EYE = 2;
27 private const int NOSE = 3;
28 private const int MOUTH = 4;
29
30 private int xml_node_num;
31
32 private string brow_tpye_path;
33 private string eye_tpye_path;
34 private string nose_tpye_path;
35 private string mouth_tpye_path;
36 private ImageList marker_type_list;
37
38 private Button[] type_button = new Button[20];
39 private const int type_button_WIDTH = 100;
40 private const int type_button_HEIGHT = 50;
41 private const int type_button_1_location_x = 450;
42 private const int type_button_1_location_y = 70;
43
44
45 #region 构造函数,初始化
46 public Form1()
47 {
48 InitializeComponent();
49
50 Init();
51
52 }
53 #endregion
54
55 private void Init()
56 {// 一些初始化
57
58 all_picture_path = new List<string>();
59 all_picture_name = new List<string>();
60 current_picture_index = 0;
61
62 function_select = 0;
63
64 xml_node_num = 0;
65
66 // 需要修改 标记类型模板 路径
67 //brow_tpye_path = "E:\\huangtao7\\C#\\project\\Image_mark\\brow\\";
68 //eye_tpye_path = "E:\\huangtao7\\C#\\project\\Image_mark\\eye\\";
69 //nose_tpye_path = "E:\\huangtao7\\C#\\project\\Image_mark\\nose\\";
70 //mouth_tpye_path = "E:\\huangtao7\\C#\\project\\Image_mark\\mouth\\";
71 // 相对路径
72 brow_tpye_path = ".\\brow\\";
73 eye_tpye_path = ".\\eye\\";
74 nose_tpye_path = ".\\nose\\";
75 mouth_tpye_path = ".\\mouth\\";
76
77 marker_type_list = new ImageList();
78 marker_type_list.ImageSize = new Size(100, 60);
79
80 // 显示方式
81 listView1.View = View.LargeIcon;
82 listView1.LabelEdit = false;
83 listView1.AllowColumnReorder = false;
84 listView1.CheckBoxes = false;
85 listView1.FullRowSelect = false;
86 listView1.GridLines = false;
87 listView1.BorderStyle = BorderStyle.None;
88 listView1.Sorting = SortOrder.Ascending;
89
90 Using_select_picture_button(false);
91 reselect_button.Visible = false;
92
93 }
94
95 #region 根据标记功能设置 ListView 显示样例
96 void Set_example_picture()
97 {
98 marker_type_list.Images.Clear();
99 listView1.Items.Clear();
100
101 switch(function_select)
102 {
103 case BROW:
104 {
105 #region 显示眉毛的样例
106 DirectoryInfo TheFolder = new DirectoryInfo(brow_tpye_path);
107 List<string> brow_type_name = new List<string>();
108
109 foreach (FileInfo NextFile in TheFolder.GetFiles("*.jpg"))
110 {
111 marker_type_list.Images.Add(Image.FromFile(brow_tpye_path + @"\" + NextFile.Name));
112 brow_type_name.Add(NextFile.Name);
113
114 }
115
116 listView1.LargeImageList = marker_type_list;
117 for (int i = 0; i < marker_type_list.Images.Count; i++)
118 {
119 listView1.Items.Add(brow_type_name[i]);
120 listView1.Items[i].ImageIndex = i;
121 }
122 #endregion
123 }
124 break;
125 case EYE:
126 {
127 #region 显示眼睛的样例
128 DirectoryInfo TheFolder = new DirectoryInfo(eye_tpye_path);
129 List<string> eye_type_name = new List<string>();
130
131 foreach (FileInfo NextFile in TheFolder.GetFiles("*.jpg"))
132 {
133 marker_type_list.Images.Add(Image.FromFile(eye_tpye_path + @"\" + NextFile.Name));
134 eye_type_name.Add(NextFile.Name);
135
136 }
137
138 listView1.LargeImageList = marker_type_list;
139 for (int i = 0; i < marker_type_list.Images.Count; i++)
140 {
141 listView1.Items.Add(eye_type_name[i]);
142 listView1.Items[i].ImageIndex = i;
143 }
144 #endregion
145 }
146 break;
147 case NOSE:
148 {
149 #region 显示鼻子的样例
150 DirectoryInfo TheFolder = new DirectoryInfo(nose_tpye_path);
151 List<string> nose_type_name = new List<string>();
152
153 foreach (FileInfo NextFile in TheFolder.GetFiles("*.jpg"))
154 {
155 marker_type_list.Images.Add(Image.FromFile(nose_tpye_path + @"\" + NextFile.Name));
156 nose_type_name.Add(NextFile.Name);
157
158 }
159
160 listView1.LargeImageList = marker_type_list;
161 for (int i = 0; i < marker_type_list.Images.Count; i++)
162 {
163 listView1.Items.Add(nose_type_name[i]);
164 listView1.Items[i].ImageIndex = i;
165 }
166 #endregion
167 }
168 break;
169 case MOUTH:
170 {
171 #region 显示嘴巴的样例
172 DirectoryInfo TheFolder = new DirectoryInfo(mouth_tpye_path);
173 List<string> mouth_type_name = new List<string>();
174
175 foreach (FileInfo NextFile in TheFolder.GetFiles("*.jpg"))
176 {
177 marker_type_list.Images.Add(Image.FromFile(mouth_tpye_path + @"\" + NextFile.Name));
178 mouth_type_name.Add(NextFile.Name);
179
180 }
181
182 listView1.LargeImageList = marker_type_list;
183 for (int i = 0; i < marker_type_list.Images.Count; i++)
184 {
185 listView1.Items.Add(mouth_type_name[i]);
186 listView1.Items[i].ImageIndex = i;
187 }
188 #endregion
189 }
190 break;
191 default: break;
192 }
193
194
195 }
196 #endregion
197
198 #region 根据标记功能加载相应的 XML 文件,设置按钮
199 void Load_xml_set_button()
200 {
201 XmlDocument xmlDoc = new XmlDocument();
202 XmlReaderSettings settings = new XmlReaderSettings();
203 settings.IgnoreComments = true;
204
205 OpenFileDialog openFileDialog1 = new OpenFileDialog();
206
207 openFileDialog1.InitialDirectory = @"E:\";
208 openFileDialog1.Filter = "xml files (*.xml)|*.xml";
209 openFileDialog1.RestoreDirectory = true;
210
211 // 先把之前的功能按钮释放
212 if(xml_node_num != 0)
213 {
214 for (int i = 0; i < xml_node_num; i++)
215 type_button[i].Dispose();
216 }
217
218 string xml_type = "";
219 switch(function_select)
220 {
221 case BROW: xml_type = "brow"; break;
222 case EYE: xml_type = "eye"; break;
223 case NOSE: xml_type = "nose"; break;
224 case MOUTH: xml_type = "mouth"; break;
225 }
226
227 if ((openFileDialog1.ShowDialog() == DialogResult.OK) && (openFileDialog1.FileName != ""))
228 {
229 string xml_path = openFileDialog1.FileName;
230
231 XmlReader reader = XmlReader.Create(xml_path, settings);
232 xmlDoc.Load(reader);
233
234 if (xmlDoc.DocumentElement.ChildNodes.Count <= 0)
235 {
236 MessageBox.Show("该 xml 无配置信息,请重新选择");
237 return;
238 }
239 if (xmlDoc.DocumentElement.ChildNodes[0].Name != xml_type)
240 {
241 MessageBox.Show("该 xml 与标记功能不对应,请重新选择");
242 return;
243 }
244 }
245 else
246 {
247 return;
248 }
249
250 // 标记类型样本数量
251 xml_node_num = xmlDoc.DocumentElement.ChildNodes.Count;
252
253 //int x = type_button_1_location_x, y = type_button_1_location_y;
254 int x = 10, y = 20;
255 int x_button_num = 0;
256 for (int i = 0; i < xml_node_num; i++)
257 {
258 type_button[i] = new Button();
259 type_button[i].Location = new Point(x, y);
260 type_button[i].Size = new Size(type_button_WIDTH, type_button_HEIGHT);
261 //type_button[i].Name = ((XmlElement)xmlDoc.DocumentElement.ChildNodes[i]).GetAttribute("ID").ToString();
262 type_button[i].Name = ( "B" + i.ToString() );
263 type_button[i].Text = ((XmlElement)xmlDoc.DocumentElement.ChildNodes[i]).GetAttribute("type").ToString();
264 type_button[i].Click += new System.EventHandler(this.type_button_Click);
265
266 this.groupBox1.Controls.Add(type_button[i]);
267
268 x += 140;
269 ++x_button_num;
270 if (x_button_num == 4)
271 {
272 x = 10;
273 x_button_num = 0;
274 y += 60;
275 }
276
277 }
278
279 Set_example_picture();
280
281 Using_select_picture_button(false);
282
283
284 }
285 #endregion
286
287 #region 标记选项按钮消息
288 private void type_button_Click(object sender, EventArgs e)
289 {
290 //MessageBox.Show(((Button)sender).Text + " was clicked !");
291
292 Select_one_type_button(sender);
293
294 Write_output_xml(sender);
295
296 Using_select_picture_button(true);
297 }
298 #endregion
299
300 #region 写图片信息到 xml 输出文件
301 private void Write_output_xml(object sender)
302 {
303 if (!File.Exists(@"output.xml"))
304 {
305 XmlTextWriter output_xml = new XmlTextWriter("output.xml", Encoding.UTF8);
306 output_xml.Formatting = Formatting.Indented;
307 output_xml.WriteStartDocument(false);
308
309 output_xml.WriteStartElement("图片标记信息");
310
311 output_xml.WriteComment("这是使用软件标记后输出的图片信息");
312
313 output_xml.WriteEndElement();
314
315 output_xml.Flush();
316 output_xml.Close();
317 }
318
319 XmlDocument xmldoc = new XmlDocument();
320 xmldoc.Load("output.xml");
321
322 XmlNode root = xmldoc.SelectSingleNode("图片标记信息");
323
324 switch(function_select)
325 {
326 case BROW:
327 {
328 if(if_mark_the_picture(root, function_select))
329 {
330 MessageBox.Show("该图片此类型已经标记过");
331 return;
332 }
333
334 // 查找xml中是否有当前图片信息,有的话不要创建节点,直接添加
335 XmlNodeList nodelist = root.ChildNodes;
336 if (nodelist.Count > 0)
337 {
338 foreach (XmlNode node1 in nodelist)
339 {
340 if (node1.Name == all_picture_name[current_picture_index - 1])
341 {
342 node1.Attributes["brow_type"].Value = ((Button)sender).Text;
343
344 xmldoc.Save("output.xml");
345
346 return;
347 }
348 }
349 }
350
351 //创建一个<Node>节点
352 XmlElement xe1 = xmldoc.CreateElement(all_picture_name[current_picture_index - 1]);
353
354 //设置该节点 type 属性
355 xe1.SetAttribute("brow_type", ((Button)sender).Text);
356
357 if (xe1.Attributes["eye_type"] == null)
358 xe1.SetAttribute("eye_type", "");
359 if (xe1.Attributes["nose_type"] == null)
360 xe1.SetAttribute("nose_type", "");
361 if (xe1.Attributes["mouth_type"] == null)
362 xe1.SetAttribute("mouth_type", "");
363
364 //添加到<图片标记信息>节点中
365 root.AppendChild(xe1);
366
367 xmldoc.Save("output.xml");
368 }
369 break;
370 case EYE:
371 {
372 if (if_mark_the_picture(root, function_select))
373 {
374 MessageBox.Show("该图片此类型已经标记过");
375 return;
376 }
377
378 // 查找xml中是否有当前图片信息,有的话不要创建节点,直接添加
379 XmlNodeList nodelist = root.ChildNodes;
380 if (nodelist.Count > 0)
381 {
382 foreach (XmlNode node1 in nodelist)
383 {
384 if (node1.Name == all_picture_name[current_picture_index - 1])
385 {
386 node1.Attributes["eye_type"].Value = ((Button)sender).Text;
387
388 xmldoc.Save("output.xml");
389
390 return;
391 }
392 }
393 }
394
395 //创建一个<Node>节点
396 XmlElement xe1 = xmldoc.CreateElement(all_picture_name[current_picture_index - 1]);
397
398 //设置该节点 type 属性
399 if (xe1.Attributes["brow_type"] == null)
400 xe1.SetAttribute("brow_type", "");
401
402 xe1.SetAttribute("eye_type", ((Button)sender).Text);
403
404 if (xe1.Attributes["nose_type"] == null)
405 xe1.SetAttribute("nose_type", "");
406 if (xe1.Attributes["mouth_type"] == null)
407 xe1.SetAttribute("mouth_type", "");
408
409 //添加到<图片标记信息>节点中
410 root.AppendChild(xe1);
411
412 xmldoc.Save("output.xml");
413
414 }
415 break;
416 case NOSE:
417 {
418 if (if_mark_the_picture(root, function_select))
419 {
420 MessageBox.Show("该图片此类型已经标记过");
421 return;
422 }
423
424 // 查找xml中是否有当前图片信息,有的话不要创建节点,直接添加
425 XmlNodeList nodelist = root.ChildNodes;
426 if (nodelist.Count > 0)
427 {
428 foreach (XmlNode node1 in nodelist)
429 {
430 if (node1.Name == all_picture_name[current_picture_index - 1])
431 {
432 node1.Attributes["nose_type"].Value = ((Button)sender).Text;
433
434 xmldoc.Save("output.xml");
435
436 return;
437 }
438 }
439 }
440
441 //创建一个<Node>节点
442 XmlElement xe1 = xmldoc.CreateElement(all_picture_name[current_picture_index - 1]);
443
444 //设置该节点 type 属性
445
446 if (xe1.Attributes["brow_type"] == null)
447 xe1.SetAttribute("brow_type", "");
448 if (xe1.Attributes["eye_type"] == null)
449 xe1.SetAttribute("eye_type", "");
450
451 xe1.SetAttribute("nose_type", ((Button)sender).Text);
452
453 if (xe1.Attributes["mouth_type"] == null)
454 xe1.SetAttribute("mouth_type", "");
455
456 //添加到<图片标记信息>节点中
457 root.AppendChild(xe1);
458
459 xmldoc.Save("output.xml");
460
461 }
462 break;
463 case MOUTH:
464 {
465 if (if_mark_the_picture(root, function_select))
466 {
467 MessageBox.Show("该图片此类型已经标记过");
468 return;
469 }
470
471 // 查找xml中是否有当前图片信息,有的话不要创建节点,直接添加
472 XmlNodeList nodelist = root.ChildNodes;
473 if (nodelist.Count > 0)
474 {
475 foreach (XmlNode node1 in nodelist)
476 {
477 if (node1.Name == all_picture_name[current_picture_index - 1])
478 {
479 node1.Attributes["mouth_type"].Value = ((Button)sender).Text;
480
481 xmldoc.Save("output.xml");
482
483 return;
484 }
485 }
486 }
487
488 //创建一个<Node>节点
489 XmlElement xe1 = xmldoc.CreateElement(all_picture_name[current_picture_index - 1]);
490
491 //设置该节点 type 属性
492
493 if (xe1.Attributes["brow_type"] == null)
494 xe1.SetAttribute("brow_type", "");
495 if (xe1.Attributes["eye_type"] == null)
496 xe1.SetAttribute("eye_type", "");
497 if (xe1.Attributes["nose_type"] == null)
498 xe1.SetAttribute("nose_type", "");
499
500 xe1.SetAttribute("mouth_type", ((Button)sender).Text);
501
502 //添加到<图片标记信息>节点中
503 root.AppendChild(xe1);
504
505 xmldoc.Save("output.xml");
506
507 }
508 break;
509 default: break;
510 }
511 }
512 #endregion
513
514 #region 此图片该功能类型是否标记过 标记过的返回 true
515 private bool if_mark_the_picture(XmlNode root, int function)
516 {
517 //得到顶层节点列表
518 //XmlNodeList topM = xmld.DocumentElement.ChildNodes;
519
520 XmlNodeList nodelist = root.ChildNodes;
521 if (nodelist.Count > 0)
522 {
523 foreach(XmlNode node1 in nodelist)
524 {
525 if(node1.Name == all_picture_name[current_picture_index - 1])
526 {
527 switch (function)
528 {
529 case BROW:
530 {
531 if (node1.Attributes["brow_type"].Value != "")
532 return true;
533 }
534 break;
535 case EYE:
536 {
537 if (node1.Attributes["eye_type"].Value != "")
538 return true;
539 }
540 break;
541 case NOSE:
542 {
543 if (node1.Attributes["nose_type"].Value != "")
544 return true;
545 }
546 break;
547 case MOUTH:
548 {
549 if (node1.Attributes["mouth_type"].Value != "")
550 return true;
551 }
552 break;
553 default: break;
554
555 }
556 }
557 }
558 }
559 return false;
560
561 }
562 #endregion
563
564 #region 设置图片路径
565 private void 打开ToolStripMenuItem_Click(object sender, EventArgs e)
566 {
567 current_picture_path = "";
568 all_picture_path.Clear();
569 all_picture_name.Clear();
570
571 FolderBrowserDialog FolderBrowserDialog1 = new FolderBrowserDialog();
572 FolderBrowserDialog1.Description = "请选择图片路径:";
573
574 if (FolderBrowserDialog1.ShowDialog() == DialogResult.OK)
575 {
576 current_picture_path = FolderBrowserDialog1.SelectedPath;
577
578 DirectoryInfo TheFolder = new DirectoryInfo(current_picture_path);
579 List<string> all = new List<string>();
580
581 foreach (FileInfo NextFile in TheFolder.GetFiles("*.jpg"))
582 {
583 all.Add(NextFile.Name);
584
585 }
586 foreach (FileInfo NextFile in TheFolder.GetFiles("*.bmp"))
587 {
588 all.Add(NextFile.Name);
589
590 }
591 foreach (FileInfo NextFile in TheFolder.GetFiles("*.png"))
592 {
593 all.Add(NextFile.Name);
594
595 }
596
597 if(all.Count > 0)
598 {
599 for (int i = 0; i < all.Count; i++)
600 {
601 all_picture_path.Add(current_picture_path + @"\" + all[i]);
602 all_picture_name.Add(all[i]);
603 }
604
605 current_picture_index = 1;
606
607 // 显示图片
608 pictureBox1.Load(all_picture_path[current_picture_index - 1]);
609
610 Using_select_picture_button(true);
611 reselect_button.Visible = true;
612
613 }
614 else
615 {
616 MessageBox.Show("此路径下无图片,重新设置");
617 }
618
619 }
620 else
621 {
622 return;
623 }
624 }
625
626 #endregion
627
628 #region 上一张或下一张图片
629 private void buttonLeft_Click(object sender, EventArgs e)
630 {
631 if(xml_node_num != 0)
632 Using_select_picture_button(false);
633
634 if (current_picture_index > 1)
635 {
636 --current_picture_index;
637 }
638 else
639 current_picture_index = all_picture_path.Count;
640
641 pictureBox1.Load(all_picture_path[current_picture_index - 1]);
642
643 switch (function_select)
644 {
645 case BROW:
646 {
647 label1.Text = "正在 标记眉毛...第 " + current_picture_index.ToString() + " 张图片";
648 }
649 break;
650 case EYE:
651 {
652 label1.Text = "正在 标记眼睛...第 " + current_picture_index.ToString() + " 张图片";
653 }
654 break;
655 case NOSE:
656 {
657 label1.Text = "正在 标记鼻子...第 " + current_picture_index.ToString() + " 张图片";
658 }
659 break;
660 case MOUTH:
661 {
662 label1.Text = "正在 标记嘴巴...第 " + current_picture_index.ToString() + " 张图片";
663 }
664 break;
665 default: break;
666 }
667 All_type_button_ok();
668
669 }
670
671 private void buttonRight_Click(object sender, EventArgs e)
672 {
673 if (xml_node_num != 0)
674 Using_select_picture_button(false);
675
676 if (current_picture_index < all_picture_path.Count )
677 {
678 ++current_picture_index;
679 }
680 else
681 current_picture_index = 1;
682
683 pictureBox1.Load(all_picture_path[current_picture_index - 1]);
684
685 switch(function_select)
686 {
687 case BROW:
688 {
689 label1.Text = "正在 标记眉毛...第 " + current_picture_index.ToString() + " 张图片";
690 }
691 break;
692 case EYE:
693 {
694 label1.Text = "正在 标记眼睛...第 " + current_picture_index.ToString() + " 张图片";
695 }
696 break;
697 case NOSE:
698 {
699 label1.Text = "正在 标记鼻子...第 " + current_picture_index.ToString() + " 张图片";
700 }
701 break;
702 case MOUTH:
703 {
704 label1.Text = "正在 标记嘴巴...第 " + current_picture_index.ToString() + " 张图片";
705 }
706 break;
707 default: break;
708 }
709 All_type_button_ok();
710
711 }
712 #endregion
713
714 #region 浏览图片
715 private void reselect_button_Click(object sender, EventArgs e)
716 {
717 Using_select_picture_button(true);
718 }
719 #endregion
720
721 #region 标记功能选择
722 private void 标记眉毛ToolStripMenuItem_Click(object sender, EventArgs e)
723 {
724 function_select = BROW;
725
726 if (all_picture_path.Count != 0)
727 {
728 label1.Text = "正在 标记眉毛...第 " + current_picture_index.ToString() + " 张图片";
729
730 }
731 else
732 {
733 MessageBox.Show("先设置图片路径");
734 return;
735 }
736
737 Load_xml_set_button();
738
739 }
740
741 private void 标记眼睛ToolStripMenuItem_Click(object sender, EventArgs e)
742 {
743
744 function_select = EYE;
745
746 if(all_picture_path.Count != 0)
747 {
748 label1.Text = "正在 标记眼睛...第 " + current_picture_index.ToString() + " 张图片";
749
750 }
751 else
752 {
753 MessageBox.Show("先设置图片路径");
754 return;
755 }
756
757 Load_xml_set_button();
758 }
759
760 private void 标记鼻子ToolStripMenuItem_Click(object sender, EventArgs e)
761 {
762 function_select = NOSE;
763
764 if (all_picture_path.Count != 0)
765 {
766 label1.Text = "正在 标记鼻子...第 " + current_picture_index.ToString() + " 张图片";
767
768 }
769 else
770 {
771 MessageBox.Show("先设置图片路径");
772 return;
773 }
774
775 Load_xml_set_button();
776 }
777
778 private void 标记嘴巴ToolStripMenuItem_Click(object sender, EventArgs e)
779 {
780 function_select = MOUTH;
781
782 if (all_picture_path.Count != 0)
783 {
784 label1.Text = "正在 标记嘴巴...第 " + current_picture_index.ToString() + " 张图片";
785
786 }
787 else
788 {
789 MessageBox.Show("先设置图片路径");
790 return;
791 }
792
793 Load_xml_set_button();
794 }
795 #endregion
796
797 #region 是否使图片选择按钮不可见
798 private void Using_select_picture_button(bool if_or_not)
799 {
800 if(if_or_not == true)
801 {
802 buttonLeft.Visible = true;
803 buttonRight.Visible = true;
804 }
805 else
806 {
807 buttonLeft.Visible = false;
808 buttonRight.Visible = false;
809 }
810
811 }
812 #endregion
813
814 #region 选择一种类型后,使该按钮禁用,使其它类型按钮不可见
815 private void Select_one_type_button(object sender)
816 {
817 for(int i=0;i < xml_node_num; i++)
818 {
819 if(type_button[i].Name == ((Button)sender).Name)
820 {
821 type_button[i].Enabled = false;
822
823 }
824 else
825 {
826 type_button[i].Visible = false;
827 }
828 }
829
830 }
831 #endregion
832
833 #region 使所有类型按钮可用可见
834 private void All_type_button_ok()
835 {
836 if (xml_node_num != 0)
837 {
838 for (int i = 0; i < xml_node_num; i++)
839 {
840 type_button[i].Visible = true;
841 type_button[i].Enabled = true;
842 }
843 }
844 else
845 return;
846
847 }
848 #endregion
849
850 }
851 }