init commit
This commit is contained in:
@@ -0,0 +1,295 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
|
||||
namespace AForge.Imaging;
|
||||
|
||||
public class DocumentSkewChecker
|
||||
{
|
||||
private int stepsPerDegree;
|
||||
|
||||
private int houghHeight;
|
||||
|
||||
private double thetaStep;
|
||||
|
||||
private double maxSkewToDetect;
|
||||
|
||||
private double[] sinMap;
|
||||
|
||||
private double[] cosMap;
|
||||
|
||||
private bool needToInitialize = true;
|
||||
|
||||
private short[,] houghMap;
|
||||
|
||||
private short maxMapIntensity;
|
||||
|
||||
private int localPeakRadius = 4;
|
||||
|
||||
private ArrayList lines = new ArrayList();
|
||||
|
||||
public int StepsPerDegree
|
||||
{
|
||||
get
|
||||
{
|
||||
return stepsPerDegree;
|
||||
}
|
||||
set
|
||||
{
|
||||
stepsPerDegree = System.Math.Max(1, System.Math.Min(10, value));
|
||||
needToInitialize = true;
|
||||
}
|
||||
}
|
||||
|
||||
public double MaxSkewToDetect
|
||||
{
|
||||
get
|
||||
{
|
||||
return maxSkewToDetect;
|
||||
}
|
||||
set
|
||||
{
|
||||
maxSkewToDetect = System.Math.Max(0.0, System.Math.Min(45.0, value));
|
||||
needToInitialize = true;
|
||||
}
|
||||
}
|
||||
|
||||
[Obsolete("The property is deprecated and setting it has not any effect. Use MaxSkewToDetect property instead.")]
|
||||
public double MinBeta
|
||||
{
|
||||
get
|
||||
{
|
||||
return 0.0 - maxSkewToDetect;
|
||||
}
|
||||
set
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
[Obsolete("The property is deprecated and setting it has not any effect. Use MaxSkewToDetect property instead.")]
|
||||
public double MaxBeta
|
||||
{
|
||||
get
|
||||
{
|
||||
return maxSkewToDetect;
|
||||
}
|
||||
set
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public int LocalPeakRadius
|
||||
{
|
||||
get
|
||||
{
|
||||
return localPeakRadius;
|
||||
}
|
||||
set
|
||||
{
|
||||
localPeakRadius = System.Math.Max(1, System.Math.Min(10, value));
|
||||
}
|
||||
}
|
||||
|
||||
public DocumentSkewChecker()
|
||||
{
|
||||
StepsPerDegree = 10;
|
||||
MaxSkewToDetect = 30.0;
|
||||
}
|
||||
|
||||
public double GetSkewAngle(Bitmap image)
|
||||
{
|
||||
return GetSkewAngle(image, new Rectangle(0, 0, ((Image)image).Width, ((Image)image).Height));
|
||||
}
|
||||
|
||||
public double GetSkewAngle(Bitmap image, Rectangle rect)
|
||||
{
|
||||
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_000b: Invalid comparison between Unknown and I4
|
||||
if ((int)((Image)image).PixelFormat != 198659)
|
||||
{
|
||||
throw new UnsupportedImageFormatException("Unsupported pixel format of the source image.");
|
||||
}
|
||||
BitmapData val = image.LockBits(new Rectangle(0, 0, ((Image)image).Width, ((Image)image).Height), (ImageLockMode)1, (PixelFormat)198659);
|
||||
try
|
||||
{
|
||||
return GetSkewAngle(new UnmanagedImage(val), rect);
|
||||
}
|
||||
finally
|
||||
{
|
||||
image.UnlockBits(val);
|
||||
}
|
||||
}
|
||||
|
||||
public double GetSkewAngle(BitmapData imageData)
|
||||
{
|
||||
return GetSkewAngle(new UnmanagedImage(imageData), new Rectangle(0, 0, imageData.Width, imageData.Height));
|
||||
}
|
||||
|
||||
public double GetSkewAngle(BitmapData imageData, Rectangle rect)
|
||||
{
|
||||
return GetSkewAngle(new UnmanagedImage(imageData), rect);
|
||||
}
|
||||
|
||||
public double GetSkewAngle(UnmanagedImage image)
|
||||
{
|
||||
return GetSkewAngle(image, new Rectangle(0, 0, image.Width, image.Height));
|
||||
}
|
||||
|
||||
public unsafe double GetSkewAngle(UnmanagedImage image, Rectangle rect)
|
||||
{
|
||||
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_000b: Invalid comparison between Unknown and I4
|
||||
if ((int)image.PixelFormat != 198659)
|
||||
{
|
||||
throw new UnsupportedImageFormatException("Unsupported pixel format of the source image.");
|
||||
}
|
||||
InitHoughMap();
|
||||
int width = image.Width;
|
||||
int height = image.Height;
|
||||
int num = width / 2;
|
||||
int num2 = height / 2;
|
||||
rect.Intersect(new Rectangle(0, 0, width, height));
|
||||
int num3 = -num + rect.Left;
|
||||
int num4 = -num2 + rect.Top;
|
||||
int num5 = width - num - (width - rect.Right);
|
||||
int num6 = height - num2 - (height - rect.Bottom) - 1;
|
||||
int num7 = image.Stride - rect.Width;
|
||||
int num8 = (int)System.Math.Sqrt(num * num + num2 * num2);
|
||||
int num9 = num8 * 2;
|
||||
houghMap = new short[houghHeight, num9];
|
||||
byte* ptr = (byte*)image.ImageData.ToPointer() + (nint)rect.Top * (nint)image.Stride + rect.Left;
|
||||
byte* ptr2 = ptr + image.Stride;
|
||||
for (int i = num4; i < num6; i++)
|
||||
{
|
||||
int num10 = num3;
|
||||
while (num10 < num5)
|
||||
{
|
||||
if (*ptr < 128 && *ptr2 >= 128)
|
||||
{
|
||||
for (int j = 0; j < houghHeight; j++)
|
||||
{
|
||||
int num11 = (int)(cosMap[j] * (double)num10 - sinMap[j] * (double)i) + num8;
|
||||
if (num11 >= 0 && num11 < num9)
|
||||
{
|
||||
houghMap[j, num11]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
num10++;
|
||||
ptr++;
|
||||
ptr2++;
|
||||
}
|
||||
ptr += num7;
|
||||
ptr2 += num7;
|
||||
}
|
||||
maxMapIntensity = 0;
|
||||
for (int k = 0; k < houghHeight; k++)
|
||||
{
|
||||
for (int l = 0; l < num9; l++)
|
||||
{
|
||||
if (houghMap[k, l] > maxMapIntensity)
|
||||
{
|
||||
maxMapIntensity = houghMap[k, l];
|
||||
}
|
||||
}
|
||||
}
|
||||
CollectLines((short)(width / 10));
|
||||
HoughLine[] mostIntensiveLines = GetMostIntensiveLines(5);
|
||||
double num12 = 0.0;
|
||||
double num13 = 0.0;
|
||||
HoughLine[] array = mostIntensiveLines;
|
||||
foreach (HoughLine houghLine in array)
|
||||
{
|
||||
if (houghLine.RelativeIntensity > 0.5)
|
||||
{
|
||||
num12 += houghLine.Theta * houghLine.RelativeIntensity;
|
||||
num13 += houghLine.RelativeIntensity;
|
||||
}
|
||||
}
|
||||
if (mostIntensiveLines.Length > 0)
|
||||
{
|
||||
num12 /= num13;
|
||||
}
|
||||
return num12 - 90.0;
|
||||
}
|
||||
|
||||
private HoughLine[] GetMostIntensiveLines(int count)
|
||||
{
|
||||
int num = System.Math.Min(count, lines.Count);
|
||||
HoughLine[] array = new HoughLine[num];
|
||||
lines.CopyTo(0, array, 0, num);
|
||||
return array;
|
||||
}
|
||||
|
||||
private void CollectLines(short minLineIntensity)
|
||||
{
|
||||
int length = houghMap.GetLength(0);
|
||||
int length2 = houghMap.GetLength(1);
|
||||
int num = length2 >> 1;
|
||||
lines.Clear();
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
for (int j = 0; j < length2; j++)
|
||||
{
|
||||
short num2 = houghMap[i, j];
|
||||
if (num2 < minLineIntensity)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
bool flag = false;
|
||||
int k = i - localPeakRadius;
|
||||
for (int num3 = i + localPeakRadius; k < num3; k++)
|
||||
{
|
||||
if (k < 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (k >= length || flag)
|
||||
{
|
||||
break;
|
||||
}
|
||||
int l = j - localPeakRadius;
|
||||
for (int num4 = j + localPeakRadius; l < num4; l++)
|
||||
{
|
||||
if (l >= 0)
|
||||
{
|
||||
if (l >= length2)
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (houghMap[k, l] > num2)
|
||||
{
|
||||
flag = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!flag)
|
||||
{
|
||||
lines.Add(new HoughLine(90.0 - maxSkewToDetect + (double)i / (double)stepsPerDegree, (short)(j - num), num2, (double)num2 / (double)maxMapIntensity));
|
||||
}
|
||||
}
|
||||
}
|
||||
lines.Sort();
|
||||
}
|
||||
|
||||
private void InitHoughMap()
|
||||
{
|
||||
if (needToInitialize)
|
||||
{
|
||||
needToInitialize = false;
|
||||
houghHeight = (int)(2.0 * maxSkewToDetect * (double)stepsPerDegree);
|
||||
thetaStep = 2.0 * maxSkewToDetect * System.Math.PI / 180.0 / (double)houghHeight;
|
||||
sinMap = new double[houghHeight];
|
||||
cosMap = new double[houghHeight];
|
||||
double num = 90.0 - maxSkewToDetect;
|
||||
for (int i = 0; i < houghHeight; i++)
|
||||
{
|
||||
sinMap[i] = System.Math.Sin(num * System.Math.PI / 180.0 + (double)i * thetaStep);
|
||||
cosMap[i] = System.Math.Cos(num * System.Math.PI / 180.0 + (double)i * thetaStep);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user