目录
背景
工具界面
操作
1、选择目录
2、更改为正确的信息
3、保存
4、说明
项目
代码
下载
背景
为什么要写这么一个小工具呢?因为要对文字进行标注。
为什么对文字进行标注呢?因为要重新训练识别。
为什么要重新训练识别呢?因为通用OCR识别识别不了。(通用OCR识别参考 https://lw112190.blog.csdn.net/article/details/133784164)
什么样子的图片通用OCR识别不了呢?它来了,如下图
放大看一个
识别不了的原因主要是特殊字体+横线干扰
打算重新训练之前,做过哪些努力呢?
1、更换精度更高的服务器端模型,效果不好,放弃
2、图片预处理,去掉文字后面的横线(去掉文字后面横线参考:https://lw112190.blog.csdn.net/article/details/134283487),再识别,效果不好,放弃。
所以自己标注,重新训练了。
训练效果如何?暂时还不知道,因为标注工作还没完成。
工具界面
操作
1、选择目录
选择后默认加载第一章图片
文本框里面的字哪里来的呢,是我用通用OCR识别的,虽然效果不好,但是还是能识别一些,标注的时候可以少打几个字。
2、更改为正确的信息
3、保存
点击保存,或者键盘Enter,自动加载下一张图片,效率还不错。
4、说明
默认会在选择的目录下生成两个文件夹,标注不会对原数据进行任何处理。
target存放标注好保存的文件。
cache记录一下标注的文件,方便后续工作(比如今天标不完了,关机下班,明天来了打开工具,可以从昨天标注的图片的下一张图片继续标注)。
项目
代码
代码写的比较糙,因为只是一个临时性的工具,需要的可以根据自己的需要修改、重构。
using OpenCvSharp;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace OpenCvSharp_Demo
{
public partial class frmMain : Form
{
public frmMain()
{
InitializeComponent();
}
int index = -1;
Mat src;
String name;
String ImageFolderPath;
String TargetFolderPath;
String CacheFolderPath;
List<String> ImgFile = new List<string>();
List<String> CacheImgFile = new List<string>();
//下一张
private void button2_Click(object sender, EventArgs e)
{
index = index + 1;
if (index > ImgFile.Count - 1)
{
index = ImgFile.Count;
MessageBox.Show("下一张没有了,干完了!");
return;
}
ShowImg(index);
}
//上一张
private void button4_Click(object sender, EventArgs e)
{
index = index - 1;
if (index < 0)
{
MessageBox.Show("上一张没有了");
index = 0;
return;
}
ShowImg(index);
}
private void ShowImg(int index)
{
name = ImgFile[index];
txtName.Text = name.Split('.')[0];
txtInfo.Text = name + " " + index + "/" + ImgFile.Count;
if (File.Exists(CacheFolderPath + name.Split('.')[0] + ".txt"))
{
string info = System.IO.File.ReadAllText(CacheFolderPath + name.Split('.')[0] + ".txt");
if (info.StartsWith("del_"))
{
//已经标注
txtInfo.Text = name + "[标记为删除] " + (index + 1).ToString() + "/" + ImgFile.Count;
}
else
{
//已经标注
txtInfo.Text = name + "[已经标注] " + (index + 1) + "/" + ImgFile.Count;
txtName.Text = info;
}
}
else
{
//未标注
txtInfo.Text = name + " " + (index + 1) + "/" + ImgFile.Count;
}
if (src!=null)
{
src.Dispose();
}
if (pictureBox2.Image != null)
{
pictureBox2.Image.Dispose();
}
src = new Mat(ImageFolderPath + name);
pictureBox2.Image = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(src);
}
//保存
private void button1_Click(object sender, EventArgs e)
{
//保存图片
Cv2.ImWrite(TargetFolderPath + txtName.Text + "." + name.Split('.')[1], src);
//写个缓存
FileStream fs = new FileStream(CacheFolderPath + name.Split('.')[0] + ".txt", FileMode.Create);
StreamWriter sw = new StreamWriter(fs, Encoding.UTF8);
sw.WriteLine(txtName.Text);
sw.Close();
fs.Close();
if (pictureBox2.Image != null)
{
pictureBox2.Image.Dispose();
}
if (src != null)
{
src.Dispose();
}
//下一张
button2_Click(null, null);
}
/// <summary>
/// 选择目录
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button3_Click(object sender, EventArgs e)
{
FolderBrowserDialog dialog = new FolderBrowserDialog();
if (dialog.ShowDialog(this) != DialogResult.OK)
{
return;
}
ImageFolderPath = dialog.SelectedPath + "\\";
TargetFolderPath = ImageFolderPath + "target\\";
CacheFolderPath = ImageFolderPath + "cache\\";
if (!Directory.Exists(TargetFolderPath))
{
Directory.CreateDirectory(TargetFolderPath);
}
DirectoryInfo root = new DirectoryInfo(ImageFolderPath);
foreach (FileInfo f in root.GetFiles())
{
if (f.Extension.Contains(".jpg") || f.Extension.Contains(".jpeg") || f.Extension.Contains(".png"))
{
ImgFile.Add(f.Name);
}
}
if (ImgFile.Count == 0)
{
MessageBox.Show("没有图片");
return;
}
txtInfo.Text = "共计[" + ImgFile.Count + "]张图片";
if (!Directory.Exists(CacheFolderPath))
{
Directory.CreateDirectory(CacheFolderPath);
}
else
{
//定位上一次标注的位置,然后下一张
root = new DirectoryInfo(CacheFolderPath);
foreach (FileInfo f in root.GetFiles())
{
if (f.Extension.Contains(".txt"))
{
CacheImgFile.Add(f.Name);
}
}
if (CacheImgFile.Count > 0)
{
string lastImg = CacheImgFile.Last();
lastImg = lastImg.Split('.')[0];
string temp = ImgFile.Find(o => o.StartsWith(lastImg));
if (!string.IsNullOrEmpty(temp))
{
index = ImgFile.IndexOf(temp);
}
}
}
//自动下一张
button2_Click(null, null);
}
//删除
private void button5_Click(object sender, EventArgs e)
{
//保存
Cv2.ImWrite(TargetFolderPath + "del_" + txtName.Text + "." + name.Split('.')[1], src);
//写个缓存
FileStream fs = new FileStream(CacheFolderPath + name.Split('.')[0] + ".txt", FileMode.Create);
StreamWriter sw = new StreamWriter(fs, Encoding.UTF8);
sw.WriteLine("del_" + txtName.Text);
sw.Close();
fs.Close();
if (pictureBox2.Image != null)
{
pictureBox2.Image.Dispose();
}
if (!src.Empty())
{
src.Dispose();
}
//下一张
button2_Click(null, null);
}
}
}
下载
源码下载