Note that there are some explanatory texts on larger screens.

plurals
  1. PONonspecific exception when running unsafe code to process images
    text
    copied!<p>I'm doing some image processing and ran in to an exception.</p> <p>Let me explain the logic process;</p> <ul> <li>Resize the image to to a smaller size</li> <li>Turn it grayscale</li> <li>Threshold the image</li> <li>Save it for use later on.</li> </ul> <p>When you threshold the image, the constructor <strong>can</strong> take an int that sets the intensity of the filter. The best way I've found to get this "magic number" is to use a method called GetOtsuThreshold. It uses unsafe code but works well. However, something strange happens when you call that method. After you call the otsu method, it causes the Aforge...Threshold.ApplyInPlace() method to throw a <em>Parameter is not valid</em> exception. If you don't call it (<em>When the code is commented out</em>) the whole thing runs just fine though.</p> <p>Wot's the deal?</p> <p>EDIT: Found the problem; You must put a new a new image into the otsu method because it disposes of the image!!</p> <pre><code>using System; using System.Drawing; using System.Drawing.Imaging; using AForge.Imaging.Filters; namespace Puma.Ocr.Tests { class FormatImage { public static Bitmap _FullImageOfCoin; public FormatImage(string path) { _FullImageOfCoin = ScaleImage(new Bitmap(path), 2000, 2000); GrayscaleImage(); ThresholdImage(); } private void GrayscaleImage() { Grayscale filter = new Grayscale(0.2125, 0.7154, 0.0721); // apply the filter _FullImageOfCoin = filter.Apply(_FullImageOfCoin); } private void ThresholdImage() { //Causes the exception Threshold threshold = new Threshold(getOtsuThreshold(_FullImageOfCoin)); //Runs fine //Threshold threshold = new Threshold(); threshold.ApplyInPlace(_FullImageOfCoin); _FullImageOfCoin.Save(@"C:\users\school\desktop\thresholded.bmp"); } public static Bitmap ScaleImage(Bitmap image, int maxWidth, int maxHeight) { var ratioX = (double)maxWidth / image.Width; var ratioY = (double)maxHeight / image.Height; var ratio = Math.Min(ratioX, ratioY); var newWidth = (int)(image.Width * ratio); var newHeight = (int)(image.Height * ratio); var newImage = new Bitmap(newWidth, newHeight); Graphics.FromImage(newImage).DrawImage(image, 0, 0, newWidth, newHeight); return newImage; } public int getOtsuThreshold(Bitmap bmp) { byte t = 0; float[] vet = new float[256]; int[] hist = new int[256]; vet.Initialize(); float p1, p2, p12; int k; BitmapData bmData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb); unsafe { byte* p = (byte*)(void*)bmData.Scan0.ToPointer(); getHistogram(p, bmp.Width, bmp.Height, bmData.Stride, hist); for (k = 1; k != 255; k++) { p1 = Px(0, k, hist); p2 = Px(k + 1, 255, hist); p12 = p1 * p2; if (p12 == 0) p12 = 1; float diff = (Mx(0, k, hist) * p2) - (Mx(k + 1, 255, hist) * p1); vet[k] = (float)diff * diff / p12; } } bmp.UnlockBits(bmData); t = (byte)findMax(vet, 256); bmp.Dispose(); return t; } private unsafe void getHistogram(byte* p, int w, int h, int ws, int[] hist) { hist.Initialize(); for (int i = 0; i &lt; h; i++) { for (int j = 0; j &lt; w * 3; j += 3) { int index = i * ws + j; hist[p[index]]++; } } } private int findMax(float[] vec, int n) { float maxVec = 0; int idx = 0; int i; for (i = 1; i &lt;= n - 1; i++) { if (vec[i] &gt; maxVec) { maxVec = vec[i]; idx = i; } } return idx; } private float Px(int init, int end, int[] hist) { int sum = 0; int i; for (i = init; i &lt;= end; i++) sum += hist[i]; return (float)sum; } // function is used to compute the mean values in the equation (mu) private float Mx(int init, int end, int[] hist) { int sum = 0; int i; for (i = init; i &lt;= end; i++) sum += i * hist[i]; return (float)sum; } } } </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload