dev - OCR complete !

master
hy.kim 1 year ago
parent 81386531ff
commit f0585d3567

@ -0,0 +1,84 @@
<Window x:Class="ScreenShotOCR.CaptureWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:ScreenShotOCR"
mc:Ignorable="d"
Title="CaptureWindow" Height="800" Width="600" WindowStyle="None" ResizeMode="NoResize" WindowState="Maximized" AllowsTransparency="True">
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Rectangle Height="30" Fill="#FF5291FF" Margin="0,0,0,770" VerticalAlignment="Top" />
<TextBlock Text="ScreenShot OCR - CaptureWindow" FontWeight="Bold" Margin="10,10,365,770" Height="20" VerticalAlignment="Top"/>
<TextBlock Text="by PINB" HorizontalAlignment="Right" FontSize="10" FontStyle="Italic" Margin="0,12,0,768" Width="50" Height="20" VerticalAlignment="Top"/>
<Button x:Name="copyBtn" Width="120" Height="20" Content="Copy to clipboard" Margin="340,35,140,0" VerticalAlignment="Top" Background="#FFFFE752" BorderBrush="#FFFFE752" Click="copyBtn_Click">
<Button.Resources>
<Style TargetType="{x:Type Border}">
<Setter Property="CornerRadius" Value="10"/>
<Setter Property="Effect">
<Setter.Value>
<DropShadowEffect Color="Black" Direction="320" ShadowDepth="3" BlurRadius="5" Opacity="0.5" />
</Setter.Value>
</Setter>
</Style>
<Style TargetType="{x:Type Button}">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<!--<Setter Property="Background" Value="White"/>
<Setter Property="BorderBrush" Value="White"/>-->
<Setter Property="Foreground" Value="Orange"/>
</Trigger>
</Style.Triggers>
</Style>
</Button.Resources>
</Button>
<Button x:Name="ClearBtn" Width="60" Height="20" Content="Clear" Margin="465,35,75,0" VerticalAlignment="Top" Background="#FFA852FF" BorderBrush="#FFA852FF" Click="ClearBtn_Click">
<Button.Resources>
<Style TargetType="{x:Type Border}">
<Setter Property="CornerRadius" Value="10"/>
<Setter Property="Effect">
<Setter.Value>
<DropShadowEffect Color="Black" Direction="320" ShadowDepth="3" BlurRadius="5" Opacity="0.5" />
</Setter.Value>
</Setter>
</Style>
<Style TargetType="{x:Type Button}">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<!--<Setter Property="Background" Value="White"/>
<Setter Property="BorderBrush" Value="White"/>-->
<Setter Property="Foreground" Value="Purple"/>
</Trigger>
</Style.Triggers>
</Style>
</Button.Resources>
</Button>
<Button x:Name="Close" Width="60" Height="20" Content="Close" Margin="530,35,10,0" VerticalAlignment="Top" Background="#FFFF5252" BorderBrush="#FFFF5252" Click="Close_Click">
<Button.Resources>
<Style TargetType="{x:Type Border}">
<Setter Property="CornerRadius" Value="10"/>
<Setter Property="Effect">
<Setter.Value>
<DropShadowEffect Color="Black" Direction="320" ShadowDepth="3" BlurRadius="5" Opacity="0.5" />
</Setter.Value>
</Setter>
</Style>
<Style TargetType="{x:Type Button}">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<!--<Setter Property="Background" Value="White"/>
<Setter Property="BorderBrush" Value="White"/>-->
<Setter Property="Foreground" Value="Red"/>
</Trigger>
</Style.Triggers>
</Style>
</Button.Resources>
</Button>
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="10,60,10,10">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="55*"/>
<ColumnDefinition Width="3*"/>
</Grid.ColumnDefinitions>
<Image x:Name="ScreenView" Stretch="Fill" MouseDown="ScreenView_MouseDown" MouseMove="ScreenView_MouseMove" MouseUp="ScreenView_MouseUp" Grid.ColumnSpan="2"/>
</Grid>
</Grid>
</Window>

@ -0,0 +1,225 @@
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
namespace ScreenShotOCR
{
/// <summary>
/// CaptureWindow.xaml에 대한 상호 작용 논리
/// </summary>
public partial class CaptureWindow : Window
{
public EventHandlerGrab m_handlerGrab = null;
Bitmap bitmap = null;
Bitmap crop = null;
Image bg = null;
int screen_w = (int)SystemParameters.PrimaryScreenWidth;
int screen_h = (int)SystemParameters.PrimaryScreenHeight;
System.Drawing.Rectangle roi = new System.Drawing.Rectangle();
float resX = 1.0f;
float resY = 1.0f;
bool bClicked = false;
System.Drawing.PointF pt = new System.Drawing.PointF();
public CaptureWindow()
{
InitializeComponent();
SetTransparent(true);
m_handlerGrab = delegate ()
{
var crop = bitmap.Clone(roi, bitmap.PixelFormat);
return crop;
};
}
public void SetTransparent(bool enable)
{
if (enable)
{
this.Background = System.Windows.Media.Brushes.Transparent;
ScreenView.Source = null;
}
else
{
this.Background = System.Windows.Media.Brushes.White;
}
}
private void Window_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
this.DragMove();
}
public void copyBtn_Click(object sender, RoutedEventArgs e)
{
try
{
//new Task(delegate
//{
SetTransparent(false);
if (bitmap != null) bitmap.Dispose();
if (bg != null) { bg.Dispose(); }
bitmap = new Bitmap(screen_w, screen_h, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
var gr = Graphics.FromImage(bitmap);
gr.CopyFromScreen(0, 0, 0, 0, bitmap.Size);
string name = "snapshot.png";
bg = ResizeImage(bitmap, new System.Drawing.Size(screen_w, screen_h));
ScreenView.Source = ConvertToImageSource(bg);
bitmap.Save(name, ImageFormat.Png);
gr.Dispose();
//}, TaskCreationOptions.DenyChildAttach).Start();
}
catch (Exception ex)
{
}
}
public static Bitmap ResizeImage(Bitmap imgToResize, System.Drawing.Size size)
{
try
{
Bitmap b = new Bitmap(size.Width, size.Height);
using (Graphics g = Graphics.FromImage((Image)b))
{
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
g.DrawImage(imgToResize, 0, 0, size.Width, size.Height);
}
return b;
}
catch
{
Console.WriteLine("Bitmap could not be resized");
return imgToResize;
}
}
private ImageSource ConvertToImageSource(Image image)
{
using (var ms = new MemoryStream())
{
image.Save(ms, ImageFormat.Bmp);
ms.Seek(0, SeekOrigin.Begin);
var bitmapImage = new BitmapImage();
bitmapImage.BeginInit();
bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
bitmapImage.StreamSource = ms;
bitmapImage.EndInit();
return bitmapImage;
}
}
private void ClearBtn_Click(object sender, RoutedEventArgs e)
{
SetTransparent(true);
}
private void Close_Click(object sender, RoutedEventArgs e)
{
this.Visibility = Visibility.Hidden;
}
private void ScreenView_MouseDown(object sender, MouseButtonEventArgs e)
{
if (!bClicked)
{
bClicked = true;
var p = e.GetPosition(ScreenView);
float x = Convert.ToSingle(Math.Round(p.X * resX));
float y = Convert.ToSingle(Math.Round(p.Y * resY));
pt = new System.Drawing.PointF(x, y);
roi.X = Convert.ToInt32(x);
roi.Y = Convert.ToInt32(y);
}
}
private void ScreenView_MouseMove(object sender, MouseEventArgs e)
{
if (bClicked)
{
var p = e.GetPosition(ScreenView);
float x = Convert.ToSingle(p.X);
float y = Convert.ToSingle(p.Y);
var w = (float)Math.Round(x * resX - pt.X);
var h = (float)Math.Round(y * resY - pt.Y);
roi.Width = Convert.ToInt32(w);
roi.Height = Convert.ToInt32(h);
CheckROI();
DrawROI();
}
}
private void ScreenView_MouseUp(object sender, MouseButtonEventArgs e)
{
if (bClicked)
{
var p = e.GetPosition(ScreenView);
float x = Convert.ToSingle(p.X);
float y = Convert.ToSingle(p.Y);
var w = (float)Math.Round(x * resX - pt.X);
var h = (float)Math.Round(y * resY - pt.Y);
roi.Width = Convert.ToInt32(w);
roi.Height = Convert.ToInt32(h);
CheckROI();
DrawROI();
bClicked = false;
}
}
private void CheckROI()
{
int x = roi.X;
if (x < 0) { x = 0; } else if (x >= screen_w) { x = screen_w - 1; }
int y = roi.Y;
if (y < 0) { y = 0; } else if (y >= screen_h) { y = screen_h - 1; }
int w = roi.Width;
if (w < 0) { w = 0; } else if (x + w >= screen_w) { w = screen_w - 1 - x; }
int h = roi.Height;
if (h < 0) { h = 0; } else if (y + h >= screen_h) { h = screen_h - 1 - y; }
roi = new System.Drawing.Rectangle(x, y, w, h);
}
private void DrawROI()
{
if (bg == null) return;
try
{
int x = (int)Math.Round(Convert.ToSingle(roi.X / resX));
int y = (int)Math.Round(Convert.ToSingle(roi.Y / resY));
int w = (int)Math.Round(Convert.ToSingle(roi.Width / resX));
int h = (int)Math.Round(Convert.ToSingle(roi.Height / resY));
System.Drawing.Pen pen = new System.Drawing.Pen(System.Drawing.Color.Red, 1);
System.Drawing.Rectangle rect = new System.Drawing.Rectangle(x, y, w, h);
var tmp = (Bitmap)bg.Clone();
var gr = Graphics.FromImage(tmp);
gr.DrawRectangle(pen, rect);
ScreenView.Source = ConvertToImageSource(tmp);
//posX.Text = roi.X.ToString();
//posY.Text = roi.Y.ToString();
//posW.Text = roi.Width.ToString();
//posH.Text = roi.Height.ToString();
gr.Dispose();
tmp.Dispose();
}
catch
{
}
}
}
}

@ -13,7 +13,7 @@
<TextBlock Text="ScreenShot OCR" FontWeight="Bold" Margin="15,8,265,422" Width="120" Height="20"/>
<TextBlock Text="v 1.0" FontSize="8" FontWeight="Light" Margin="116,12,234,418" Width="50" Height="20"/>
<TextBlock Text="by PINB" HorizontalAlignment="Right" FontSize="10" FontStyle="Italic" Margin="0,10,0,420" Width="50" Height="20"/>
<Button Width="60" Height="20" Content="Capture" Margin="10,35,330,395" Background="#FF5291FF" BorderBrush="#FF5291FF">
<Button x:Name="CaptureBtn" Width="60" Height="20" Content="Capture" Margin="200,35,140,395" Background="#FF5291FF" BorderBrush="#FF5291FF" Click="CaptureBtn_Click">
<Button.Resources>
<Style TargetType="{x:Type Border}">
<Setter Property="CornerRadius" Value="10"/>
@ -34,8 +34,7 @@
</Style>
</Button.Resources>
</Button>
<Button Width="60" Height="20" Content="OCR" Margin="75,35,265,395" Background="#FF52FF89" BorderBrush="#FF52FF89">
<Button x:Name="OCRBtn" Width="60" Height="20" Content="OCR" Margin="265,35,75,395" Background="#FF52FF89" BorderBrush="#FF52FF89" Click="OCRBtn_Click">
<Button.Resources>
<Style TargetType="{x:Type Border}">
<Setter Property="CornerRadius" Value="10"/>
@ -56,49 +55,8 @@
</Style>
</Button.Resources>
</Button>
<Button Width="120" Height="20" Content="Copy to clipboard" Margin="140,35,140,395" Background="#FFFFE752" BorderBrush="#FFFFE752">
<Button.Resources>
<Style TargetType="{x:Type Border}">
<Setter Property="CornerRadius" Value="10"/>
<Setter Property="Effect">
<Setter.Value>
<DropShadowEffect Color="Black" Direction="320" ShadowDepth="3" BlurRadius="5" Opacity="0.5" />
</Setter.Value>
</Setter>
</Style>
<Style TargetType="{x:Type Button}">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<!--<Setter Property="Background" Value="White"/>
<Setter Property="BorderBrush" Value="White"/>-->
<Setter Property="Foreground" Value="Orange"/>
</Trigger>
</Style.Triggers>
</Style>
</Button.Resources>
</Button>
<Button Width="60" Height="20" Content="Settings" Margin="265,35,75,395" Background="#FFA852FF" BorderBrush="#FFA852FF">
<Button.Resources>
<Style TargetType="{x:Type Border}">
<Setter Property="CornerRadius" Value="10"/>
<Setter Property="Effect">
<Setter.Value>
<DropShadowEffect Color="Black" Direction="320" ShadowDepth="3" BlurRadius="5" Opacity="0.5" />
</Setter.Value>
</Setter>
</Style>
<Style TargetType="{x:Type Button}">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<!--<Setter Property="Background" Value="White"/>
<Setter Property="BorderBrush" Value="White"/>-->
<Setter Property="Foreground" Value="Purple"/>
</Trigger>
</Style.Triggers>
</Style>
</Button.Resources>
</Button>
<Button Width="60" Height="20" Content="Close" Margin="335,35,5,395" Background="#FFFF5252" BorderBrush="#FFFF5252">
<Button x:Name="Close" Width="60" Height="20" Content="Close" Margin="330,35,10,395" Background="#FFFF5252" BorderBrush="#FFFF5252" Click="Close_Click">
<Button.Resources>
<Style TargetType="{x:Type Border}">
<Setter Property="CornerRadius" Value="10"/>
@ -119,7 +77,7 @@
</Style>
</Button.Resources>
</Button>
<Image Margin="0,60,10,10" Name="window1" Width="380" Height="380" HorizontalAlignment="Right"/>
<TextBox x:Name="textblock" HorizontalAlignment="Left" Height="380" Margin="10,60,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="380" AcceptsReturn="True"/>
</Grid>
</Window>

@ -1,25 +1,21 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Drawing;
using System.IO;
using System.Drawing.Imaging;
using PINBlog;
namespace ScreenShotOCR
{
public delegate Bitmap EventHandlerGrab();
/// <summary>
/// MainWindow.xaml에 대한 상호 작용 논리
/// </summary>
public partial class MainWindow : Window
{
CaptureWindow m_cw = new CaptureWindow();
public MainWindow()
{
InitializeComponent();
@ -29,5 +25,42 @@ namespace ScreenShotOCR
{
this.DragMove();
}
private void CaptureBtn_Click(object sender, RoutedEventArgs e)
{
m_cw.Show();
this.Topmost = true;
}
private void Close_Click(object sender, RoutedEventArgs e)
{
m_cw.Close();
this.Close();
}
private void OCRBtn_Click(object sender, RoutedEventArgs e)
{
Bitmap crop = m_cw.m_handlerGrab();
Tesseract(crop);
}
private bool Tesseract(Image image)
{
try
{
MemoryStream stream = new MemoryStream();
image.Save(stream, ImageFormat.Png);
var tesseract = new Tesseract();
var result = tesseract.GetText(stream);
textblock.Text = result;
return true;
}
catch (Exception ex)
{
return false;
}
}
}
}

@ -37,6 +37,10 @@
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Drawing" />
<Reference Include="System.Drawing.Common, Version=7.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>packages\System.Drawing.Common.7.0.0\lib\net462\System.Drawing.Common.dll</HintPath>
</Reference>
<Reference Include="System.Xml" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Core" />
@ -55,6 +59,14 @@
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</ApplicationDefinition>
<Compile Include="CaptureWindow.xaml.cs">
<DependentUpon>CaptureWindow.xaml</DependentUpon>
</Compile>
<Compile Include="Tesseract.cs" />
<Page Include="CaptureWindow.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="MainWindow.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
@ -86,13 +98,18 @@
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
<None Include="packages.config" />
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
<None Include="tessdata\eng.traineddata" />
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
</ItemGroup>
<ItemGroup>
<Content Include="tessdata\tesseract.exe" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

@ -0,0 +1,169 @@
using System;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Text;
namespace PINBlog
{
public enum LANGUAGE { ENG = 0 }
public class OCRResultInfo
{
public LANGUAGE Language { get; set; }
public string Result { get; set; }
public OCRResultInfo()
{
Language = LANGUAGE.ENG;
Result = "";
}
}
public class Tesseract
{
private string m_TesseractExePath;
private LANGUAGE m_Language;
/// <summary>
/// Initializes a new instance of the <see cref="TesseractService"/> class.
/// </summary>
/// <param name="tesseractDir">The path for the Tesseract4 installation folder (C:\Program Files\Tesseract-OCR).</param>
/// <param name="language">The language used to extract text from images (eng, por, etc)</param>
/// <param name="dataDir">The data with the trained models (tessdata). Download the models from https://github.com/tesseract-ocr/tessdata_fast</param>
public Tesseract(LANGUAGE language = LANGUAGE.ENG)
{
// Tesseract configs.
var dir = Path.Combine(".", "tessdata");
m_TesseractExePath = Path.Combine(dir,"tesseract.exe");
m_Language = language;
Environment.SetEnvironmentVariable("TESSDATA_PREFIX", dir);
}
public Stream ToStream(Image image, ImageFormat format = null)
{
var stream = new System.IO.MemoryStream();
if (format == null)
{
image.Save(stream, image.RawFormat);
}
else
{
image.Save(stream, format);
}
stream.Position = 0;
return stream;
}
/// <summary>
/// Read text from the images streams.
/// </summary>
/// <param name="images">The images streams.</param>
/// <returns>The images text.</returns>
public string GetText(params Stream[] images)
{
var output = string.Empty;
if (images.Any())
{
var tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
Directory.CreateDirectory(tempPath);
var tempInputFile = NewTempFileName(tempPath);
var tempOutputFile = NewTempFileName(tempPath);
try
{
WriteInputFiles(images, tempPath, tempInputFile);
var info = new ProcessStartInfo
{
FileName = m_TesseractExePath,
Arguments = $"{tempInputFile} {tempOutputFile} -l {m_Language.ToString()}",
RedirectStandardError = true,
RedirectStandardOutput = true,
CreateNoWindow = true,
UseShellExecute = false
};
using (var ps = Process.Start(info))
{
ps.WaitForExit();
var exitCode = ps.ExitCode;
if (exitCode == 0)
{
output = File.ReadAllText(tempOutputFile + ".txt");
var charset = new char[] { ' ', '\n', '\f' };
output = output.TrimStart(charset).TrimEnd(charset);
}
else
{
var stderr = ps.StandardError.ReadToEnd();
throw new InvalidOperationException(stderr);
}
}
}
finally
{
Directory.Delete(tempPath, true);
}
}
return output;
}
private void WriteInputFiles(Stream[] inputStreams, string tempPath, string tempInputFile)
{
// If there is more thant one image file, so build the list file using the images as input files.
if (inputStreams.Length > 1)
{
var imagesListFileContent = new StringBuilder();
foreach (var inputStream in inputStreams)
{
var imageFile = NewTempFileName(tempPath);
using (var tempStream = File.OpenWrite(imageFile))
{
CopyStream(inputStream, tempStream);
}
imagesListFileContent.AppendLine(imageFile);
}
File.WriteAllText(tempInputFile, imagesListFileContent.ToString());
}
else
{
// If is only one image file, than use the image file as input file.
using (var tempStream = File.OpenWrite(tempInputFile))
{
CopyStream(inputStreams.First(), tempStream);
}
}
}
private void CopyStream(Stream input, Stream output)
{
if (input.CanSeek)
input.Seek(0, SeekOrigin.Begin);
//input.CopyTo(output);
Byte[] buffer = new byte[input.Length];
int len = input.Read(buffer, 0, buffer.Length);
output.Write(buffer, 0, len);
input.Close();
}
private string NewTempFileName(string tempPath)
{
return Path.Combine(tempPath, Guid.NewGuid().ToString());
}
}
}

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="System.Drawing.Common" version="7.0.0" targetFramework="net472" />
</packages>

Binary file not shown.

Binary file not shown.
Loading…
Cancel
Save