Files
SuperVPN/output/Libraries/AForge.Imaging/AForge/Imaging/DocumentSkewChecker.cs
2025-10-09 09:57:24 +09:00

296 lines
6.6 KiB
C#

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);
}
}
}
}