Improve italic detection for "Binary image compare" OCR - thx tormento :)

+ a few related improvements
See doom9 posts around http://forum.doom9.net/showthread.php?p=1910580#post1910580
This commit is contained in:
Nikolaj Olsson 2020-05-17 09:29:12 +02:00
parent d3039ac40a
commit 44e686593a
9 changed files with 172 additions and 33 deletions

View File

@ -2765,6 +2765,16 @@
<Word from="AII's" to="All's" />
<Word from="FIog" to="Flog" />
<Word from="SIit" to="Slit" />
<Word from="allsummer" to="all summer" />
<Word from="couldhave" to="could have" />
<Word from="flrst" to="first" />
<Word from="likeyou" to="like you" />
<Word from="makeyou" to="make you" />
<Word from="ofmysenioryear" to="of my senior year" />
<Word from="thatparty" to="that party" />
<Word from="thatpeople" to="that people" />
<Word from="thatperson" to="that person" />
<Word from="thoughyou" to="though you" />
</WholeWords>
<PartialWordsAlways>
<!-- Will be replaced always -->

View File

@ -2532,7 +2532,7 @@ Keep changes?</KeepChangesMessage>
<EditImageDb>Edit image db</EditImageDb>
</VobSubOcr>
<VobSubOcrCharacter>
<Title>VobSub - Manual image to text</Title>
<Title>OCR - Manual image to text</Title>
<ShrinkSelection>Shrink selection</ShrinkSelection>
<ExpandSelection>Expand selection</ExpandSelection>
<SubtitleImage>Subtitle image</SubtitleImage>

Binary file not shown.

View File

@ -2869,7 +2869,7 @@ Keep changes?",
VobSubOcrCharacter = new LanguageStructure.VobSubOcrCharacter
{
Title = "VobSub - Manual image to text",
Title = "OCR - Manual image to text",
Abort = "&Abort",
Skip = "&Skip",
SubtitleImage = "Subtitle image",

View File

@ -4031,6 +4031,11 @@ namespace Nikse.SubtitleEdit.Forms.Ocr
_vobSubOcrCharacter.Initialize(bitmap, item, _manualOcrDialogPosition, _italicCheckedLast, expandSelectionList.Count > 1, null, _lastAdditions, this);
DialogResult result = _vobSubOcrCharacter.ShowDialog(this);
_manualOcrDialogPosition = _vobSubOcrCharacter.FormPosition;
if (result == DialogResult.Cancel && _vobSubOcrCharacter.SkipImage)
{
break;
}
if (result == DialogResult.OK && _vobSubOcrCharacter.ShrinkSelection)
{
shrinkSelection = true;
@ -4089,6 +4094,12 @@ namespace Nikse.SubtitleEdit.Forms.Ocr
_vobSubOcrCharacter.Initialize(bitmap, item, _manualOcrDialogPosition, _italicCheckedLast, false, bestGuess, _lastAdditions, this, allowExpand);
DialogResult result = _vobSubOcrCharacter.ShowDialog(this);
_manualOcrDialogPosition = _vobSubOcrCharacter.FormPosition;
if (result == DialogResult.Cancel && _vobSubOcrCharacter.SkipImage)
{
break;
}
if (result == DialogResult.OK && _vobSubOcrCharacter.ExpandSelection)
{
expandSelectionList.Add(item);
@ -4171,7 +4182,11 @@ namespace Nikse.SubtitleEdit.Forms.Ocr
int wordsNotFound = _ocrFixEngine.CountUnknownWordsViaDictionary(line, out var correctWords);
// smaller space pixels for italic
if (correctWords > 0 && wordsNotFound > 0 && line.Contains("<i>", StringComparison.Ordinal) && matches.Any(p => p?.ImageSplitterItem?.CouldBeSpace == true))
if (wordsNotFound > 0 && line.Contains("<i>", StringComparison.Ordinal))
{
AddItalicCouldBeSpace(matches, parentBitmap, _unItalicFactor);
}
if (wordsNotFound > 0 && line.Contains("<i>", StringComparison.Ordinal) && matches.Any(p => p?.ImageSplitterItem?.CouldBeSpace == true))
{
int j = 0;
while (j < matches.Count)
@ -4196,7 +4211,8 @@ namespace Nikse.SubtitleEdit.Forms.Ocr
}
int tempWordsNotFound = _ocrFixEngine.CountUnknownWordsViaDictionary(tempLine, out var tempCorrectWords);
if (tempWordsNotFound == 0 && tempCorrectWords > 0)
//if (tempWordsNotFound == 0 && tempCorrectWords > 0)
if (tempWordsNotFound < wordsNotFound && tempCorrectWords > 0)
{
wordsNotFound = tempWordsNotFound;
correctWords = tempCorrectWords;
@ -4253,6 +4269,74 @@ namespace Nikse.SubtitleEdit.Forms.Ocr
return line;
}
private void AddItalicCouldBeSpace(List<CompareMatch> matches, NikseBitmap parentBitmap, double unItalicFactor)
{
for (int i = 0; i < matches.Count - 1; i++)
{
var match = matches[i];
var matchNext = matches[i + 1];
if (!match.Italic || !matchNext.Italic ||
string.IsNullOrWhiteSpace(match.Text) || string.IsNullOrWhiteSpace(matchNext.Text) ||
match.ImageSplitterItem == null || match.ImageSplitterItem.CouldBeSpace)
{
continue;
}
int blankVerticalLines = IsVerticalAngledLineTransparent(parentBitmap, match, matchNext, unItalicFactor);
if (blankVerticalLines >= _numericUpDownPixelsIsSpace)
{
matchNext.ImageSplitterItem.CouldBeSpace = true; // TODO: Rename to "could be space before"
}
}
}
private int IsVerticalAngledLineTransparent(NikseBitmap parentBitmap, CompareMatch match, CompareMatch next, double unItalicFactor)
{
int blanks = 0;
var min = match.ImageSplitterItem.X + match.ImageSplitterItem.NikseBitmap.Width;
var max = next.ImageSplitterItem.X + next.ImageSplitterItem.NikseBitmap.Width / 2;
bool abort = false;
for (int startX = min; startX < max; startX++)
{
var lineBlank = true;
for (int y = match.ImageSplitterItem.Y; y < match.ImageSplitterItem.Y + match.ImageSplitterItem.NikseBitmap.Height; y++)
{
var x = startX - (y - match.ImageSplitterItem.Y) * unItalicFactor;
if (x >= 0)
{
var color = parentBitmap.GetPixel((int)Math.Round(x), y);
if (color.A == 0)
{
// parentBitmap.SetPixel((int)Math.Round(x), y, Color.LawnGreen);
}
else
{
// parentBitmap.SetPixel((int)Math.Round(x), y, Color.Red);
lineBlank = false;
if (blanks > 0)
{
abort = true;
break;
}
}
}
}
if (abort)
{
break;
}
if (lineBlank)
{
blanks++;
}
}
//parentBitmap.GetBitmap().Save(@"J:\Temp\" + DateTime.UtcNow.Ticks + "_" + match.Text + "_" + blanks + ".bmp");
return blanks;
}
private void SetBinOcrLowercaseUppercase(int height, string text)
{
if (text == "e" && (height < _binOcrLastLowercaseHeight || _binOcrLastLowercaseHeight < 0))
@ -6513,10 +6597,7 @@ namespace Nikse.SubtitleEdit.Forms.Ocr
}
}
if (bmp != null)
{
bmp.Dispose();
}
bmp?.Dispose();
if (mp.Text != null)
{
@ -7003,6 +7084,31 @@ namespace Nikse.SubtitleEdit.Forms.Ocr
form.ShowDialog(this);
}
}
else if (e.Modifiers == (Keys.Control | Keys.Shift) && e.KeyCode == Keys.I && _ocrMethodIndex == _ocrMethodBinaryImageCompare)
{
var bmp = (Bitmap)pictureBoxSubtitleImage.Image;
if (bmp != null)
{
var nBmp = new NikseBitmap(bmp);
bmp.Dispose();
var italicFactor = _unItalicFactor;
for (var startX = 20.0; startX < nBmp.Width; startX += 20.0)
{
var x = startX;
for (int y = 0; y < nBmp.Height; y++)
{
x = startX - y * italicFactor;
if (x >= 0)
{
nBmp.SetPixel((int)Math.Round(x), y, Color.Red);
}
}
}
pictureBoxSubtitleImage.Image = nBmp.GetBitmap();
}
}
}
private void ComboBoxTesseractLanguagesSelectedIndexChanged(object sender, EventArgs e)

View File

@ -206,6 +206,7 @@
this.buttonSkip.TabIndex = 3;
this.buttonSkip.Text = "&Skip";
this.buttonSkip.UseVisualStyleBackColor = true;
this.buttonSkip.Click += new System.EventHandler(this.buttonSkip_Click);
//
// pictureBoxSubtitleImage
//

View File

@ -80,10 +80,13 @@ namespace Nikse.SubtitleEdit.Forms.Ocr
public bool ShrinkSelection { get; private set; }
public bool SkipImage { get; private set; }
internal void Initialize(Bitmap vobSubImage, ImageSplitterItem character, Point position, bool italicChecked, bool showShrink, VobSubOcr.CompareMatch bestGuess, List<VobSubOcr.ImageCompareAddition> additions, VobSubOcr vobSubForm, bool allowExpand = true)
{
ShrinkSelection = false;
ExpandSelection = false;
SkipImage = false;
textBoxCharacters.Text = string.Empty;
if (bestGuess != null)
@ -292,6 +295,12 @@ namespace Nikse.SubtitleEdit.Forms.Ocr
checkBoxItalic.Checked = !checkBoxItalic.Checked;
e.SuppressKeyPress = true;
}
else if (e.Modifiers == (Keys.Control | Keys.Shift) && e.KeyCode == Keys.S)
{
SkipImage = true;
DialogResult = DialogResult.Cancel;
e.SuppressKeyPress = true;
}
}
private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
@ -303,5 +312,10 @@ namespace Nikse.SubtitleEdit.Forms.Ocr
{
TaskbarList.StopBlink(_vobSubForm);
}
private void buttonSkip_Click(object sender, EventArgs e)
{
DialogResult = DialogResult.Cancel;
}
}
}

View File

@ -34,19 +34,19 @@
this.pictureBoxSubtitleImage = new System.Windows.Forms.PictureBox();
this.contextMenuStripListview = new System.Windows.Forms.ContextMenuStrip(this.components);
this.saveImageAsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.numericUpDown1 = new System.Windows.Forms.NumericUpDown();
this.numericUpDownItalicFactor = new System.Windows.Forms.NumericUpDown();
this.labelDescription = new System.Windows.Forms.Label();
this.saveFileDialog1 = new System.Windows.Forms.SaveFileDialog();
((System.ComponentModel.ISupportInitialize)(this.pictureBoxSubtitleImage)).BeginInit();
this.contextMenuStripListview.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.numericUpDownItalicFactor)).BeginInit();
this.SuspendLayout();
//
// buttonCancel
//
this.buttonCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.buttonCancel.ImeMode = System.Windows.Forms.ImeMode.NoControl;
this.buttonCancel.Location = new System.Drawing.Point(680, 312);
this.buttonCancel.Location = new System.Drawing.Point(794, 366);
this.buttonCancel.Name = "buttonCancel";
this.buttonCancel.Size = new System.Drawing.Size(75, 23);
this.buttonCancel.TabIndex = 8;
@ -58,7 +58,7 @@
//
this.buttonOK.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.buttonOK.ImeMode = System.Windows.Forms.ImeMode.NoControl;
this.buttonOK.Location = new System.Drawing.Point(599, 312);
this.buttonOK.Location = new System.Drawing.Point(713, 366);
this.buttonOK.Name = "buttonOK";
this.buttonOK.Size = new System.Drawing.Size(75, 23);
this.buttonOK.TabIndex = 7;
@ -74,7 +74,7 @@
this.pictureBoxSubtitleImage.ContextMenuStrip = this.contextMenuStripListview;
this.pictureBoxSubtitleImage.Location = new System.Drawing.Point(12, 47);
this.pictureBoxSubtitleImage.Name = "pictureBoxSubtitleImage";
this.pictureBoxSubtitleImage.Size = new System.Drawing.Size(743, 259);
this.pictureBoxSubtitleImage.Size = new System.Drawing.Size(857, 313);
this.pictureBoxSubtitleImage.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
this.pictureBoxSubtitleImage.TabIndex = 9;
this.pictureBoxSubtitleImage.TabStop = false;
@ -93,36 +93,37 @@
this.saveImageAsToolStripMenuItem.Text = "Save image as...";
this.saveImageAsToolStripMenuItem.Click += new System.EventHandler(this.saveImageAsToolStripMenuItem_Click);
//
// numericUpDown1
// numericUpDownItalicFactor
//
this.numericUpDown1.DecimalPlaces = 2;
this.numericUpDown1.Increment = new decimal(new int[] {
this.numericUpDownItalicFactor.DecimalPlaces = 2;
this.numericUpDownItalicFactor.Increment = new decimal(new int[] {
1,
0,
0,
131072});
this.numericUpDown1.Location = new System.Drawing.Point(12, 19);
this.numericUpDown1.Maximum = new decimal(new int[] {
this.numericUpDownItalicFactor.Location = new System.Drawing.Point(12, 19);
this.numericUpDownItalicFactor.Maximum = new decimal(new int[] {
10,
0,
0,
65536});
this.numericUpDown1.Name = "numericUpDown1";
this.numericUpDown1.Size = new System.Drawing.Size(57, 20);
this.numericUpDown1.TabIndex = 10;
this.numericUpDown1.Value = new decimal(new int[] {
this.numericUpDownItalicFactor.Name = "numericUpDownItalicFactor";
this.numericUpDownItalicFactor.Size = new System.Drawing.Size(57, 20);
this.numericUpDownItalicFactor.TabIndex = 10;
this.numericUpDownItalicFactor.Value = new decimal(new int[] {
31,
0,
0,
131072});
this.numericUpDown1.ValueChanged += new System.EventHandler(this.numericUpDown1_ValueChanged);
this.numericUpDownItalicFactor.ValueChanged += new System.EventHandler(this.numericUpDownItalicFactor_ValueChanged);
//
// labelDescription
//
this.labelDescription.AutoSize = true;
this.labelDescription.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.labelDescription.Location = new System.Drawing.Point(76, 21);
this.labelDescription.Name = "labelDescription";
this.labelDescription.Size = new System.Drawing.Size(431, 13);
this.labelDescription.Size = new System.Drawing.Size(529, 13);
this.labelDescription.TabIndex = 11;
this.labelDescription.Text = "Adjust value until text style is normal and not italic. Note that original image " +
"should be italic.";
@ -131,24 +132,27 @@
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(767, 345);
this.BackColor = System.Drawing.Color.DimGray;
this.ClientSize = new System.Drawing.Size(881, 399);
this.Controls.Add(this.labelDescription);
this.Controls.Add(this.numericUpDown1);
this.Controls.Add(this.numericUpDownItalicFactor);
this.Controls.Add(this.pictureBoxSubtitleImage);
this.Controls.Add(this.buttonCancel);
this.Controls.Add(this.buttonOK);
this.KeyPreview = true;
this.MaximizeBox = false;
this.MinimizeBox = false;
this.MinimumSize = new System.Drawing.Size(783, 384);
this.Name = "VobSubOcrSetItalicFactor";
this.ShowIcon = false;
this.ShowInTaskbar = false;
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
this.Text = "Set un-italic factor";
this.Shown += new System.EventHandler(this.VobSubOcrSetItalicFactor_Shown);
this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.VobSubOcrSetItalicFactor_KeyDown);
((System.ComponentModel.ISupportInitialize)(this.pictureBoxSubtitleImage)).EndInit();
this.contextMenuStripListview.ResumeLayout(false);
((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.numericUpDownItalicFactor)).EndInit();
this.ResumeLayout(false);
this.PerformLayout();
@ -159,7 +163,7 @@
private System.Windows.Forms.Button buttonCancel;
private System.Windows.Forms.Button buttonOK;
private System.Windows.Forms.PictureBox pictureBoxSubtitleImage;
private System.Windows.Forms.NumericUpDown numericUpDown1;
private System.Windows.Forms.NumericUpDown numericUpDownItalicFactor;
private System.Windows.Forms.Label labelDescription;
private System.Windows.Forms.SaveFileDialog saveFileDialog1;
private System.Windows.Forms.ContextMenuStrip contextMenuStripListview;

View File

@ -19,7 +19,7 @@ namespace Nikse.SubtitleEdit.Forms.Ocr
_bmp = bmp;
_factor = factor;
numericUpDown1.Value = (decimal)factor;
numericUpDownItalicFactor.Value = (decimal)factor;
Text = Configuration.Settings.Language.VobSubOcrSetItalicFactor.Title;
labelDescription.Text = Configuration.Settings.Language.VobSubOcrSetItalicFactor.Description;
@ -28,9 +28,9 @@ namespace Nikse.SubtitleEdit.Forms.Ocr
buttonCancel.Text = Configuration.Settings.Language.General.Cancel;
}
private void numericUpDown1_ValueChanged(object sender, EventArgs e)
private void numericUpDownItalicFactor_ValueChanged(object sender, EventArgs e)
{
pictureBoxSubtitleImage.Image = VobSubOcr.UnItalic(_bmp, (double)numericUpDown1.Value);
pictureBoxSubtitleImage.Image = VobSubOcr.UnItalic(_bmp, (double)numericUpDownItalicFactor.Value);
}
internal double GetUnItalicFactor()
@ -40,7 +40,7 @@ namespace Nikse.SubtitleEdit.Forms.Ocr
private void buttonOK_Click(object sender, EventArgs e)
{
_factor = (double)numericUpDown1.Value;
_factor = (double)numericUpDownItalicFactor.Value;
DialogResult = DialogResult.OK;
}
@ -101,5 +101,9 @@ namespace Nikse.SubtitleEdit.Forms.Ocr
}
}
private void VobSubOcrSetItalicFactor_Shown(object sender, EventArgs e)
{
numericUpDownItalicFactor_ValueChanged(null, null);
}
}
}