patterncsharpModerate
Finding rectangles in an image
Viewed 0 times
imagerectanglesfinding
Problem
So my this class is one in which is used to find rectangles in images that have already been pre-processed. For example the images are to be deskewed, greyscale etc. Following feedback off of various people I have been told to try and conform it to c# coding standards. I have tried to do my best but was wondering what you guys thought. The code is below:
```
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
namespace Recognition
{
public class OMRRecognition : IDisposable
{
private const int BYTES_PER_PIXEL = 3;
private const int MAX_BLACK_VALUE = 382; // (255 * 3) / 2 rounded down
private const float MIN_ZONE_MULTIPLIER = 0.85f;
private const float MAX_ZONE_MULTIPLIER = 1.15f;
private const float LINE_BROKEN_TOLERANCE = 0.10f;
private bool _bImageOpen;
private int _nBitmapWidth;
private int _nBitmapHeight;
private int _nStride;
private byte[] _baPixels;
private int _nCornerTolerance;
private int _nMaxHorBrokenAmount;
private int _nMaxVertBrokenAmount;
private Size _sExpectedZoneSize;
private Size _sMinZoneSize;
private Size _sMaxZoneSize;
public OMRRecognition()
{
SetZoneSize(new Size(10, 10));
SetCornerTolerance(5);
_bImageOpen = false;
}
public void Dispose()
{
_baPixels = null;
_bImageOpen = false;
}
public void SetZoneSize(Size zoneSize)
{
_sExpectedZoneSize = zoneSize;
_sMinZoneSize = new Size((int)(zoneSize.Width MIN_ZONE_MULTIPLIER), (int)(zoneSize.Height MIN_ZONE_MULTIPLIER));
_sMaxZoneSize = new Size((int)(zoneSize.Width MAX_ZONE_MULTIPLIER), (int)(zoneSize.Height MAX_ZONE_MULTIPLIER));
_nMaxHorBrokenAmount = (int)Math.Ceiling(zoneSize.Width * LINE_BROKEN_TOLERANC
```
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
namespace Recognition
{
public class OMRRecognition : IDisposable
{
private const int BYTES_PER_PIXEL = 3;
private const int MAX_BLACK_VALUE = 382; // (255 * 3) / 2 rounded down
private const float MIN_ZONE_MULTIPLIER = 0.85f;
private const float MAX_ZONE_MULTIPLIER = 1.15f;
private const float LINE_BROKEN_TOLERANCE = 0.10f;
private bool _bImageOpen;
private int _nBitmapWidth;
private int _nBitmapHeight;
private int _nStride;
private byte[] _baPixels;
private int _nCornerTolerance;
private int _nMaxHorBrokenAmount;
private int _nMaxVertBrokenAmount;
private Size _sExpectedZoneSize;
private Size _sMinZoneSize;
private Size _sMaxZoneSize;
public OMRRecognition()
{
SetZoneSize(new Size(10, 10));
SetCornerTolerance(5);
_bImageOpen = false;
}
public void Dispose()
{
_baPixels = null;
_bImageOpen = false;
}
public void SetZoneSize(Size zoneSize)
{
_sExpectedZoneSize = zoneSize;
_sMinZoneSize = new Size((int)(zoneSize.Width MIN_ZONE_MULTIPLIER), (int)(zoneSize.Height MIN_ZONE_MULTIPLIER));
_sMaxZoneSize = new Size((int)(zoneSize.Width MAX_ZONE_MULTIPLIER), (int)(zoneSize.Height MAX_ZONE_MULTIPLIER));
_nMaxHorBrokenAmount = (int)Math.Ceiling(zoneSize.Width * LINE_BROKEN_TOLERANC
Solution
Naming
Your constants don't follow C# naming conventions. The convention is to use PascalCase.
Additionally you appear to be using Hungarian notation on your private fields, which also is against convention.
Design
Your dispose function does not appear to do any actual disposing that would not be performed by the garbage collector.
You have Setter methods. This is a Java paradigm that is accounted for with Properties in C#.
These two if statements should have their conditions combined:
Code to interfaces
Your method:
Could easily take two
Var
You should use implicit typing when the right-hand side of the assignment makes the type obvious. For example:
Should be:
Generic Exceptions
Don't catch them. You can't handle a generic exception because you don't know what it is. Catch what you know you can handle, leave the rest.
This is a pretty egregious use of exceptions as flow control:
You throw and immediately catch an exception here, causing a return of null. Instead, return null if the image is not open.
Your constants don't follow C# naming conventions. The convention is to use PascalCase.
Additionally you appear to be using Hungarian notation on your private fields, which also is against convention.
Design
Your dispose function does not appear to do any actual disposing that would not be performed by the garbage collector.
You have Setter methods. This is a Java paradigm that is accounted for with Properties in C#.
These two if statements should have their conditions combined:
if (verticalLine.StartPoint.X = (horizontalLine.StartPoint.X - _nCornerTolerance))
{
if (horizontalLine.StartPoint.Y = (verticalLine.StartPoint.Y - _nCornerTolerance))Code to interfaces
Your method:
private Pixel[] FindTopLeftCorners(Line[] horizontalLines, Line[] verticalLines)Could easily take two
IEnumerable interfaces instead of Line[]. This allows the caller to supply any data structure that supports enumeration (which is all you use those parameters for).Var
You should use implicit typing when the right-hand side of the assignment makes the type obvious. For example:
Rectangle rect = new Rectangle(pTopLeft.X - 1, pTopLeft.Y - 1, (pTopRight.X - pTopLeft.X) + 2, (pBottomLeft.Y - pTopLeft.Y) + 2);Should be:
var rect = new Rectangle(pTopLeft.X - 1, pTopLeft.Y - 1, (pTopRight.X - pTopLeft.X) + 2, (pBottomLeft.Y - pTopLeft.Y) + 2);Generic Exceptions
Don't catch them. You can't handle a generic exception because you don't know what it is. Catch what you know you can handle, leave the rest.
This is a pretty egregious use of exceptions as flow control:
try
{
if (!_bImageOpen)
throw new Exception("An image must be opened first using the 'OpenImage' method!");
return ExtractZones();
}
catch (Exception ex)
{
return null;
}You throw and immediately catch an exception here, causing a return of null. Instead, return null if the image is not open.
if (!_bImageOpen)
return null;Code Snippets
if (verticalLine.StartPoint.X <= (horizontalLine.StartPoint.X + _nCornerTolerance) && verticalLine.StartPoint.X >= (horizontalLine.StartPoint.X - _nCornerTolerance))
{
if (horizontalLine.StartPoint.Y <= (verticalLine.StartPoint.Y + _nCornerTolerance) && horizontalLine.StartPoint.Y >= (verticalLine.StartPoint.Y - _nCornerTolerance))private Pixel[] FindTopLeftCorners(Line[] horizontalLines, Line[] verticalLines)Rectangle rect = new Rectangle(pTopLeft.X - 1, pTopLeft.Y - 1, (pTopRight.X - pTopLeft.X) + 2, (pBottomLeft.Y - pTopLeft.Y) + 2);var rect = new Rectangle(pTopLeft.X - 1, pTopLeft.Y - 1, (pTopRight.X - pTopLeft.X) + 2, (pBottomLeft.Y - pTopLeft.Y) + 2);try
{
if (!_bImageOpen)
throw new Exception("An image must be opened first using the 'OpenImage' method!");
return ExtractZones();
}
catch (Exception ex)
{
return null;
}Context
StackExchange Code Review Q#111795, answer score: 10
Revisions (0)
No revisions yet.