Bitmap CreateTestBinarizedImage(PLATE_INFO pi) { // get histogram int[,] plum = new int[pi.plateImageUnprocessed.Width, pi.plateImageUnprocessed.Height]; PixelLib.Pixels.getPixelsFromImage(pi.plateImageUnprocessed, plum); CreateHistoBounds(pi); int[] histo = new int[256]; int[] integration = new int[256]; Bitmap hBmp = new Bitmap(256, 100); HistoResults histoStats = null; historgram(plum, histo, integration, true, hBmp, pi.histoBounds, out histoStats); int[,] binarizedLum = new int[pi.plateImageUnprocessed.Width, pi.plateImageUnprocessed.Height]; BinarizeOnPlate(plum, binarizedLum, histoStats); Bitmap binBmp = new Bitmap(pi.plateImageUnprocessed.Width, pi.plateImageUnprocessed.Height); Pixels.putPixels(binBmp, binarizedLum); return(binBmp); }
void BinarizeOnPlate(int[,] inLum, int[,] outLum, HistoResults histStats) { for (int y = 0; y < outLum.GetLength(1); y++) { for (int x = 0; x < outLum.GetLength(0); x++) { if (inLum[x, y] < (histStats.darkEnergyThreshold)) { outLum[x, y] = 0; } else { outLum[x, y] = 255; } } } }
int GetRightEdgeColor(int[,] inLum, int x, int y, HistoResults histStats) { if (x < 0) { x = 0; } if (x > inLum.GetLength(0) - 4) { x = inLum.GetLength(0) - 4; } if (y < 0) { y = 0; } if (y > inLum.GetLength(1) - 1) { y = inLum.GetLength(1) - 1; } int pixAve = (inLum[x + 2, y] + inLum[x + 1, y] + inLum[x, y]) / 3; return(pixAve); }
void ProcessImage(Bitmap bmp) { try { listBoxRejectLog.Items.Clear(); if (bmp == null) { return; } // get the luminance array int[,] lum = GetLuminanceArray(bmp); int error = 0; LPROCR_Lib.LPR_PROCESS_OPTIONS processOptions; processOptions = new LPROCR_Lib.LPR_PROCESS_OPTIONS(); processOptions.EnableAutoRotationRoll = 1; processOptions.EnableRotationRoll = 1; int diagEnabled = 0; if (m_AppData.LPRDiagEnabled) { diagEnabled = 1; } // read the image int plateCount = m_LPREngine.m_LPRFuntions.ReadThisImage(lum, (int)diagEnabled, ref processOptions, ref error); // extract the plate images and detected strings PLATE_INFO[] plateInfos = new PLATE_INFO[plateCount]; // get the diag images (not plate, but full images) if (m_AppData.LPRDiagEnabled) { ClearDiagDisplayTable(); byte[,] r = new byte[bmp.Width, bmp.Height]; byte[,] g = new byte[bmp.Width, bmp.Height]; byte[,] b = new byte[bmp.Width, bmp.Height]; error = 0; m_LPREngine.m_LPRFuntions.diagsGetImage(1, r, g, b, ref error);// get the full resolution image Bitmap imageBmp = new Bitmap(bmp.Width, bmp.Height); putPixelsIntoBmp(imageBmp, r, g, b); pictureBoxDiag1.Image = imageBmp; int w = 0; int h = 0; w = bmp.Width; h = bmp.Height; // m_LPREngine.m_LPRFuntions.GetSubImageSize(ref w, ref h); Bitmap subscalledBmp = new Bitmap(w, h); r = new byte[w, h]; g = new byte[w, h]; b = new byte[w, h]; //m_LPREngine.m_LPRFuntions.diagsGetImage(0, r, g, b, ref error);// get the subscalled image int[,] edge = new int[w, h]; // m_LPREngine.m_LPRFuntions.getEdgeMapSub(edge, ref error); m_LPREngine.m_LPRFuntions.getEdgeMapFullRes(edge, ref error); ColorizeEdgeMap(edge, r, g, b); putPixelsIntoBmp(subscalledBmp, r, g, b); pictureBoxDiag2.Image = subscalledBmp; // get the intergal image r = new byte[bmp.Width, bmp.Height]; g = new byte[bmp.Width, bmp.Height]; b = new byte[bmp.Width, bmp.Height]; imageBmp = new Bitmap(bmp.Width, bmp.Height); m_LPREngine.m_LPRFuntions.GetIntegralImage(r, g, b); putPixelsIntoBmp(imageBmp, r, g, b); pictureBoxDiag3.Image = imageBmp; } // get the plates for (int p = 0; p < plateCount; p++) { float score = 0; plateInfos[p] = new PLATE_INFO(); plateInfos[p].sourceImage = bmp; plateInfos[p].sourceFileName = jpegsToProcess[m_CurrentIndex]; // get the string from the plate plateInfos[p].plateNumber = m_LPREngine.m_LPRFuntions.GetPlateString(p, ref score); // exract a bitmap of the plate itself int pw = 0; int ph = 0; m_LPREngine.m_LPRFuntions.GetPlateImageSize(p, ref pw, ref ph, false); plateInfos[p].plateImage = new Bitmap(pw, ph); m_LPREngine.m_LPRFuntions.GetPlateImage(p, plateInfos[p].plateImage); plateInfos[p].numChars = plateInfos[p].plateNumber.Length; plateInfos[p].charImages = new Bitmap[plateInfos[p].numChars]; for (int c = 0; c < plateInfos[p].numChars; c++) { plateInfos[p].charImages[c] = null; try { m_LPREngine.m_LPRFuntions.GetCharImage(p, c, out plateInfos[p].charImages[c], false); } catch (Exception ex) { m_Log.Trace(ex, ErrorLog.LOG_TYPE.INFORMATIONAL); } } }// end for each plate found if (plateCount == 0) { // perhaps we really screwed up and did not find a plate when one is really there, // allow the user to manually add the plate numbers plateInfos = new PLATE_INFO[1]; plateInfos[0] = new PLATE_INFO(); plateInfos[0].sourceImage = bmp; plateInfos[0].sourceFileName = jpegsToProcess[m_CurrentIndex]; // get the string from the plate plateInfos[0].plateNumber = "0"; plateInfos[0].plateImage = bmp;// use the main picture to fill the space plateInfos[0].numChars = 0; plateCount = 1; } // create a display ClearDisplayTable(); for (int p = 0; p < plateCount; p++) { AddPlateTabToEditPage(plateInfos[p]); } m_CurrentImageResult = plateInfos; m_HaveNewDataToStore = true; if (m_AppData.LPRDiagEnabled) { try { // get the reject log string log = m_LPREngine.m_LPRFuntions.GetRejectLog(); string[] sp = log.Split(','); foreach (string s in sp) { listBoxRejectLog.Items.Add(s); } // get the plate diagnostic images, and run a diagnostic histo on original plate images int count = m_LPREngine.m_LPRFuntions.GetNumCandidatePlates(); for (int i = 0; i < count; i++) { int w = 0; int h = 0; m_LPREngine.m_LPRFuntions.GetCandidatePlateImageSize(i, ref w, ref h); byte[,] r = new byte[w, h]; byte[,] g = new byte[w, h]; byte[,] b = new byte[w, h]; error = 0; int sucess = m_LPREngine.m_LPRFuntions.GetDiagCandidatePlateImage(i, r, g, b, ref error);// get the full resolution image if (sucess == 0) { continue; } Bitmap bt = new Bitmap(w, h); putPixelsIntoBmp(bt, r, g, b); PLATE_INFO plateDiagInfo = new PLATE_INFO(); plateDiagInfo.plateImage = bt; DrawHistoBoundsOnPlateImage(plateDiagInfo); // get the diagnostic char images from the OCR lib for (int c = 0; c < plateDiagInfo.charImages.Count(); c++) { Bitmap cBmp = null; m_LPREngine.m_LPRFuntions.GetDiagCharImage(i, c, out cBmp); plateDiagInfo.charImages[c] = cBmp; } // run diag histogram display on each plate { Bitmap plateImageUnprocessed = new Bitmap(w, h); m_LPREngine.m_LPRFuntions.GetCandidatePlateImage(i, out plateImageUnprocessed); plateDiagInfo.plateImageUnprocessed = plateImageUnprocessed; int[,] plum = new int[plateImageUnprocessed.Width, plateImageUnprocessed.Height]; PixelLib.Pixels.getPixelsFromImage(plateImageUnprocessed, plum); int[] histo = new int[256]; int[] integration = new int[256]; Bitmap hBmp = new Bitmap(256, 100); HistoResults histStats = null; plateDiagInfo.histString = historgram(plum, histo, integration, true, hBmp, plateDiagInfo.histoBounds, out histStats); plateDiagInfo.histoBmp = hBmp; } AddPlateTabToDiagPage(plateDiagInfo); } } catch (Exception ex) { MessageBox.Show(ex.Message + ex.StackTrace); } } } catch (Exception ex) { MessageBox.Show(ex.Message + ex.StackTrace); } }
string historgram(int[,] Y, int[] histogram, int[] integration, bool plateHisto, Bitmap bmp, HistogramBounds bounds, out HistoResults results) { int xStart; int xEnd; int yStart; int yEnd; results = new HistoResults(); xStart = bounds.leftEdge; xEnd = bounds.rightEdge; yStart = bounds.topEdge; yEnd = bounds.bottomEdge; int x = 0; int y = 0; int ave = 0; int aveCnt = 0; int sum = 0; for (x = xStart; x < xEnd; x++) { for (y = yStart; y < yEnd; y++) { int val = Y[x, y]; histogram[val]++; ave += val; aveCnt++; } } int area = ave; ave = ave / aveCnt; for (int i = 0; i < histogram.Length; i++) { sum += histogram[i]; integration[i] = sum; } // find where the integration hits 10% of the max area area = integration[integration.Length - 1]; results.darkEnergyThreshold = 0; for (int i = 0; i < histogram.Length; i++) { if ( integration[i] > ( (35 * area) / 100)) { results.darkEnergyThreshold = i; break; } } // get dark moment results.darkPeakCount = 0; int darkMoment = 0; for (int i = 0; i < ave; i++) { if (histogram[i] > results.darkPeakCount) { results.darkPeakCount = histogram[i]; darkMoment = i; } } // get light moment results.lightPeakCount = 0; int lightMoment = 0; for (int i = ave; i < histogram.Count(); i++) { if (histogram[i] > results.lightPeakCount) { results.lightPeakCount = histogram[i]; lightMoment = i; } } // get standard deviation from the median int median = (darkMoment + lightMoment) / 2; float stddev = 0; for (int i = 0; i < histogram.Count(); i++) { stddev += histogram[i] * Math.Abs((ave - i)); } if (area == 0) area = 1; stddev /= area; stddev = stddev * 256; string histString ="stddev = "+stddev.ToString()+ "ave = " + ave.ToString() + ", dark mnt = " + darkMoment.ToString() + ", light mnt = " + lightMoment.ToString(); ; results.ave = ave; results.lightMoment = lightMoment; results.darkMoment = darkMoment; results.stdDev = (int) stddev; Color cl; cl = Color.FromKnownColor(KnownColor.Yellow); plotCurve( bmp, histogram, bmp.Height, 0); plotCurve( bmp, integration, bmp.Height, 0); // draw a line at 1/2 mark plotLine( bmp, bmp.Width / 2, bmp.Width / 2, 0, bmp.Height, cl); plotLine( bmp, bmp.Width / 2 + 1, bmp.Width / 2 + 1, 0, bmp.Height, cl); plotLine( bmp, bmp.Width / 2 + 2, bmp.Width / 2 + 2, 0, bmp.Height, cl); // draw a line at ave int aveX = ave; cl = Color.FromKnownColor(KnownColor.Green); plotLine( bmp, aveX, aveX, 0, bmp.Height - 1, cl); plotLine( bmp, aveX + 1, aveX + 1, 0, bmp.Height - 1, cl); plotLine(bmp, aveX + 2, aveX + 2, 0, bmp.Height - 1, cl); // draw a line at darkEnergyThreshold aveX = results.darkEnergyThreshold; cl = Color.FromKnownColor(KnownColor.Azure); plotLine(bmp, aveX, aveX, 0, bmp.Height - 1, cl); plotLine(bmp, aveX + 1, aveX + 1, 0, bmp.Height - 1, cl); plotLine(bmp, aveX + 2, aveX + 2, 0, bmp.Height - 1, cl); return (histString); }
int GetRightEdgeColor(int[,] inLum, int x, int y, HistoResults histStats) { if (x < 0) x = 0; if (x > inLum.GetLength(0) - 4) x = inLum.GetLength(0) - 4; if (y < 0) y = 0; if (y > inLum.GetLength(1) - 1) y = inLum.GetLength(1) - 1; int pixAve = (inLum[x + 2, y] + inLum[x + 1, y] + inLum[x, y]) / 3; return (pixAve); }
void BinarizeOnPlate(int[,] inLum, int[,] outLum, HistoResults histStats) { for (int y = 0; y < outLum.GetLength(1); y++) { for (int x = 0; x < outLum.GetLength(0); x++) { if (inLum[x, y] < (histStats.darkEnergyThreshold)) outLum[x, y] = 0; else outLum[x, y] = 255; } } }
string historgram(int[,] Y, int[] histogram, int[] integration, bool plateHisto, Bitmap bmp, HistogramBounds bounds, out HistoResults results) { int xStart; int xEnd; int yStart; int yEnd; results = new HistoResults(); xStart = bounds.leftEdge; xEnd = bounds.rightEdge; yStart = bounds.topEdge; yEnd = bounds.bottomEdge; int x = 0; int y = 0; int ave = 0; int aveCnt = 0; int sum = 0; for (x = xStart; x < xEnd; x++) { for (y = yStart; y < yEnd; y++) { int val = Y[x, y]; histogram[val]++; ave += val; aveCnt++; } } int area = ave; ave = ave / aveCnt; for (int i = 0; i < histogram.Length; i++) { sum += histogram[i]; integration[i] = sum; } // find where the integration hits 10% of the max area area = integration[integration.Length - 1]; results.darkEnergyThreshold = 0; for (int i = 0; i < histogram.Length; i++) { if (integration[i] > ((35 * area) / 100)) { results.darkEnergyThreshold = i; break; } } // get dark moment results.darkPeakCount = 0; int darkMoment = 0; for (int i = 0; i < ave; i++) { if (histogram[i] > results.darkPeakCount) { results.darkPeakCount = histogram[i]; darkMoment = i; } } // get light moment results.lightPeakCount = 0; int lightMoment = 0; for (int i = ave; i < histogram.Count(); i++) { if (histogram[i] > results.lightPeakCount) { results.lightPeakCount = histogram[i]; lightMoment = i; } } // get standard deviation from the median int median = (darkMoment + lightMoment) / 2; float stddev = 0; for (int i = 0; i < histogram.Count(); i++) { stddev += histogram[i] * Math.Abs((ave - i)); } if (area == 0) { area = 1; } stddev /= area; stddev = stddev * 256; string histString = "stddev = " + stddev.ToString() + "ave = " + ave.ToString() + ", dark mnt = " + darkMoment.ToString() + ", light mnt = " + lightMoment.ToString();; results.ave = ave; results.lightMoment = lightMoment; results.darkMoment = darkMoment; results.stdDev = (int)stddev; Color cl; cl = Color.FromKnownColor(KnownColor.Yellow); plotCurve(bmp, histogram, bmp.Height, 0); plotCurve(bmp, integration, bmp.Height, 0); // draw a line at 1/2 mark plotLine(bmp, bmp.Width / 2, bmp.Width / 2, 0, bmp.Height, cl); plotLine(bmp, bmp.Width / 2 + 1, bmp.Width / 2 + 1, 0, bmp.Height, cl); plotLine(bmp, bmp.Width / 2 + 2, bmp.Width / 2 + 2, 0, bmp.Height, cl); // draw a line at ave int aveX = ave; cl = Color.FromKnownColor(KnownColor.Green); plotLine(bmp, aveX, aveX, 0, bmp.Height - 1, cl); plotLine(bmp, aveX + 1, aveX + 1, 0, bmp.Height - 1, cl); plotLine(bmp, aveX + 2, aveX + 2, 0, bmp.Height - 1, cl); // draw a line at darkEnergyThreshold aveX = results.darkEnergyThreshold; cl = Color.FromKnownColor(KnownColor.Azure); plotLine(bmp, aveX, aveX, 0, bmp.Height - 1, cl); plotLine(bmp, aveX + 1, aveX + 1, 0, bmp.Height - 1, cl); plotLine(bmp, aveX + 2, aveX + 2, 0, bmp.Height - 1, cl); return(histString); }