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 }