Grid letters with rectangle OCR - vb.net

I have been trying to grid each letter with rectangle on an image (on that image there is only colors white and black). I've started like this:
Dim bmp As Bitmap = Label1.Image
Dim xmax As Integer
Dim ymax As Integer
xmax = Label1.Width - 1
ymax = Label1.Height - 1
Dim top, bottom, left, right As Integer
Dim first As Boolean = True
Dim last As Boolean = False
Dim first2 As Boolean = True
Dim last2 As Boolean = False
Dim pen As Pen = Pens.Red
For x = 0 To xmax
For y = 0 To ymax
With bmp.GetPixel(x, y)
If .R = 0 And .G = 0 And .B = 0 And first = True Then
left = x
first = False
last = True
ElseIf .R = 0 And .G = 0 And .B = 0 And last = True Then
right = x
End If
End With
Next y
Next x
For y = 0 To ymax
For x = 0 To xmax
With bmp.GetPixel(x, y)
If .R = 0 And .G = 0 And .B = 0 And first2 = True Then
top = y
first2 = False
last2 = True
ElseIf .R = 0 And .G = 0 And .B = 0 And last2 = True Then
bottom = y
End If
End With
Next x
Next y
first = True
first2 = True
last = False
last2 = False
Dim rect As New Rectangle(left, top, right - left, bottom - top)
Dim g As Graphics = Graphics.FromImage(bmp)
g.DrawRectangle(pen, rect)
Label1.Image = bmp
It'll check all of the pixels on the image and it'll get the black ones, I could draw rectangle around only one letter but I couldn't more then one at the time.
Still can't use it for seperate letters.
I'll be thankful for all of your responses.

Related

VBA Format Userform Numeric Output

I have a spreadsheet/userform combo that takes user input to calculate product pricing/percent tax/and square footage in consideration to output a total cost for flooring in one of the userform's textboxes.
My userform is calculating everything correctly, but I am trying to figure out how to format the output box so that it only displays values up to two digits past the decimal (i.e. $1.00). Currently, it displays up to four digits or more beyond the decimal (as seen in the Total Area, Tax Amount, and Final Price text boxes).
My userform code is as follows (I left out some non-pertinent sections that had to do with opening and closing the userform but everything that has to do with the functioning of it is there):
Public Sub SumTool()
Dim A, B, C, D, E, F As Double
Dim x As Double
Dim finalSum As Double
Dim addUp As Double
Dim BeforePercent As Double
Dim Prcnt As Double
Dim percentALT As Double
Dim percentSum As Double
Dim i As Integer
addUp = 0
finalSum = 0
BeforePercent = 0
x = 0
i = 0
'These are all area measurements
A = 280
B = 118
C = 96
D = 243
E = 38
F = 83
Do While i < 1
'These are checks to see if checkboxes in the userform are True/False and
'correspond to the area measurements above
If LR.Value = True Then
x = x + A
Else
x = x
End If
If BR1.Value = True Then
x = x + B
Else
x = x
End If
If BR2.Value = True Then
x = x + C
Else
x = x
End If
If KT.Value = True Then
x = x + D
Else
x = x
End If
If BA.Value = True Then
x = x + E
Else
x = x
End If
If HALL.Value = True Then
x = x + F
Else
x = x
End If
i = i + 1
Loop
'I have different calculations because the user has the option of
'whether they want to include tax or not. If they do not (first option)
'no special conversions have to take place. If they do, the program has to
'take the entry and convert it from 5 or 10 to 0.05 or 0.10 and then carry
'forward with the rest of the operations
If Me.Y.Value = False Then
Prcnt = 0
addUp = x
finalSum = addUp * Me.ProductPrice.Value
Me.FinalResultsBox.Value = finalSum
Me.SqFtBox.Value = addUp
Me.TaxAmountValue.Value = 0
Else
Prcnt = Me.SalesTaxNumber.Value
addUp = x
percentALT = Prcnt * 0.01
BeforePercent = addUp * Me.ProductPrice.Value
percentSum = percentALT * BeforePercent
finalSum = BeforePercent + percentSum
Me.FinalResultsBox.Value = finalSum
Me.SqFtBox.Value = addUp
Me.TaxAmountValue.Value = percentSum
End If
End Sub
You may try something like this...
Me.FinalResultsBox.Value = Format(finalSum, "$0.00")

vb Image grid detection

Im looking for a way to detect the center of grid squares when VB.net is feed an image
I want to start with an image of a grid with blue squares like this:
Grid
and i want the program to make an array of points in the center of each square like this (points aren't centered in picture)
Grid with Red points
i dont want to modify the image, i just want to get the points. I've tried getpixel for x and y but that just returns the same point
Dim search_color As Color = Color.FromArgb(255, 64, 128, 192)
Dim background_color As Color = Color.FromArgb(255, 240, 240, 240)
Dim grid_color As Color = Color.FromArgb(255, 144, 144, 144)
Dim pix As Color
Dim liney = 0, linex = 0
Dim loc, sloc, gloc As Point
For ch As Integer = 1 To 64
For y As Integer = liney To Bmp.Height - 1
For x As Integer = linex To Bmp.Width - 1
If Bmp.GetPixel(x, y) = search_color Then
sloc = New Point(x, y)
linex = x
liney = y
x = Bmp.Width - 1
y = Bmp.Height - 1
End If
Next
Next
Dim xloc = 0
For x As Integer = sloc.X To Bmp.Width - 1
If Bmp.GetPixel(x, sloc.Y) = grid_color Then
xloc = x - 1
End If
If Bmp.GetPixel(x, sloc.Y) = background_color Then
xloc = x - 1
End If
Next
For y As Integer = sloc.Y To Bmp.Height - 1
If Bmp.GetPixel(xloc, y) = grid_color Or Bmp.GetPixel(xloc, y) = background_color Then
gloc = New Point(xloc, y - 1)
End If
Next
loc = New Point((gloc.X + sloc.X) / 2, (gloc.Y + sloc.Y) / 2)
liney = gloc.Y
linex = gloc.X + 20
ListBox1.Items.Add(loc.ToString)
Next
Try this:
I added the following controls to a form to test the code:
pbImageToScan (PictureBox) - btnAnalyzeIMG (Button) - lbResult (ListBox)
Public Class Form1
Dim arrCenters() As Point
Dim bmpToAnalyze As Bitmap
Dim search_color As Color = Color.FromArgb(255, 64, 128, 192)
Dim background_color As Color = Color.FromArgb(255, 240, 240, 240)
Dim grid_color As Color = Color.FromArgb(255, 144, 144, 144)
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
bmpToAnalyze = New Bitmap(Application.StartupPath & "\Image.bmp")
pbImageToScan.Image = Image.FromFile(Application.StartupPath & "\Image.bmp")
End Sub
Private Sub btnAnalyzeIMG_Click(sender As Object, e As EventArgs) Handles btnAnalyzeIMG.Click
FindCenters()
End Sub
Private Sub FindCenters()
bmpToAnalyze = New Bitmap(Application.StartupPath & "\Image.bmp")
pbImageToScan.Image = Image.FromFile(Application.StartupPath & "\Image.bmp")
'arrCenters is the array who will contains all centers data
ReDim arrCenters(0)
'arrCenters already starts with an element; this boolean is used to handle the first point insertion
Dim bFirstElementAddedToArray As Boolean
lbResult.Items.Clear()
Dim iIMGWidth As Integer = bmpToAnalyze.Width
Dim iIMGHeight As Integer = bmpToAnalyze.Height
'X, Y coordinates used for iterations
Dim iX As Integer = 0
Dim iY As Integer = 0
'Bitmap limits reached
Dim bExit As Boolean
'Used to skip a great part of Ys, if a match has been found along the current examinated line
Dim iDeltaYMax As Integer = 0
'Main cycle
Do While Not bExit
Dim colCurrentColor As Color = bmpToAnalyze.GetPixel(iX, iY)
If colCurrentColor = search_color Then
Dim iXStart As Integer = iX
Dim iYStart As Integer = iY
Dim iXEnd As Integer
Dim iYEnd As Integer
'Width of the Blue square
For iXEnd = iX + 1 To iIMGWidth - 1
Dim colColorSearchX As Color = bmpToAnalyze.GetPixel(iXEnd, iY)
If (colColorSearchX = background_color) Or (colColorSearchX = grid_color) Then
iXEnd -= 1
Exit For
End If
Next
'Height of the Blue square
For iYEnd = iY + 1 To iIMGHeight - 1
Dim colColorSearchY As Color = bmpToAnalyze.GetPixel(iXEnd, iYEnd)
If (colColorSearchY = background_color) Or (colColorSearchY = grid_color) Then
iYEnd -= 1
Exit For
End If
Next
iDeltaYMax = iYEnd - iYStart
'Blue square center coordinates
Dim pCenter As New Point((iXStart + iXEnd) / 2, (iYStart + iYEnd) / 2)
Dim iArrLenght As Integer = 0
If Not bFirstElementAddedToArray Then
bFirstElementAddedToArray = True
Else
iArrLenght = arrCenters.GetLength(0)
ReDim Preserve arrCenters(iArrLenght)
End If
arrCenters(iArrLenght) = pCenter
lbResult.Items.Add(pCenter.ToString)
iX = iXEnd
'Checks if the Width limit of the bitmap has been reached
If iX = (iIMGWidth - 1) Then
iX = 0
iY += iDeltaYMax + 1
iDeltaYMax = 0
Else
iX += 1
End If
Else
'Checks if the Width limit of the bitmap has been reached
If iX = (iIMGWidth - 1) Then
iX = 0
iY += iDeltaYMax + 1
iDeltaYMax = 0
Else
iX += 1
End If
End If
'Width and Height limit of the bitmap have been reached
If (iX = iIMGWidth - 1) And (iY = iIMGHeight - 1) Then
bExit = True
End If
Loop
'Draws a Red point on every center found
For Each P As Point In arrCenters
bmpToAnalyze.SetPixel(P.X, P.Y, Color.Red)
Next
pbImageToScan.Image = bmpToAnalyze
End Sub
End Class

How to convert Colored image into black and white using vb.net?

I'm Using Visual studio 10.i want to convert colored image into a black and white?
i have tried to do following code it gets success but it takes lots of time to convert. can i do convert it without using anyloop in vb.net.
Thanks In Advance
Try
Dim img As Bitmap = New Bitmap((Image.FromFile("D:\\imgnam.jpg")))
Dim c As Color
Dim i As Integer = 0
Do While (i < img.Width)
Dim j As Integer = 0
Do While (j < img.Height)
c = img.GetPixel(i, j)
Dim r As Integer = 0
r = Convert.ToInt16(c.R)
Dim g As Integer = 0
g = Convert.ToInt16(c.G)
Dim b As Integer = 0
b = Convert.ToInt16(c.B)
Dim ans As Integer = ((r _
+ (g + b)) _
/ 3)
If (ans > 128) Then
r = 255
g = 255
b = 255
Else
r = 0
g = 0
b = 0
End If
c = Color.FromArgb(r, g, b)
img.SetPixel(i, j, c)
j = (j + 1)
Loop
i = (i + 1)
Loop
img.Save("D:\\imgnamNew.jpg")
Dim Bmp1 As New Image(Of Bgr, [Byte])("D:\\imgnamNew.jpg")
ImageFrame = Bmp1
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try

ZedGraph - Force all graph panes to be the same size

I am using the ZedGraph control (zgc) to create individual stacked bar charts and display them in a single stacked column as shown in the image below.
The issue that I am having is that I have no control over the number of panes that are displayed in the control as this is determined by the number of items in a listbox. It seems that the default nature of the control allows the height of the graph panes to change depending on the number of panes that are displayed within the control.
The zgc is set to dock=fill within a panel control that is set to dock=fill within the form. I would like to force the graph panes to be a static height and when needed have a vertical scroll bar appear in the panel when the number of graph panes exceeds the height of the form. How can I go about achieving this? My code for creating and populating the zgc is posted below the image.
Private Sub CreateGraph(ByVal dat As Date)
Dim count As Integer = 0
Dim master As MasterPane = zgc.MasterPane
master.Fill = New Fill(Color.FromArgb(180, 180, 180), Color.FromArgb(180, 180, 180), 45.0F)
master.PaneList.Clear()
master.Title.IsVisible = True
master.Title.Text = "Workload for " & dat.ToShortDateString()
master.Margin.All = 10
master.InnerPaneGap = 5
master.IsCommonScaleFactor = False
For Each mach As String In lbMach.Items
rowCount = 0
Dim myPaneT As New GraphPane(New Rectangle(10, 10, 10, 10), "", "Time in Minutes", mach)
myPaneT.Fill.IsVisible = False
myPaneT.Chart.Fill = New Fill(Color.White, Color.White, 45.0F)
myPaneT.BaseDimension = 3.0F
myPaneT.XAxis.Title.IsVisible = False
myPaneT.XAxis.Scale.IsVisible = False
myPaneT.XAxis.Scale.Min = 0
myPaneT.XAxis.Scale.Max = (MeiSettings.WrkHrs * 60)
myPaneT.Legend.IsVisible = True
myPaneT.Border.IsVisible = False
myPaneT.Title.IsVisible = False
myPaneT.XAxis.MajorTic.IsOutside = False
myPaneT.XAxis.MinorTic.IsOutside = False
myPaneT.XAxis.MajorGrid.IsVisible = True
myPaneT.XAxis.MinorGrid.IsVisible = True
myPaneT.Margin.All = 1
If count = lbMach.Items.Count - 1 Then
myPaneT.XAxis.Title.IsVisible = True
myPaneT.XAxis.Scale.IsVisible = True
myPaneT.Margin.Bottom = 10
End If
If count > 0 Then
myPaneT.YAxis.Scale.IsSkipLastLabel = True
End If
myPaneT.YAxis.MinSpace = 20
myPaneT.Y2Axis.MinSpace = 20
Dim dt As DataTable = ItemsByMachineDT(mach, dat)
Dim myCurve As BarItem
If dt.Rows.Count > 0 Then
Dim profName As String = Nothing
Dim timeDur() As Double
For Each dr As DataRow In dt.Rows
If profName = dr("PRO").ToString() Then
timeDur = {((Convert.ToDouble(dr("QTY")) / Convert.ToDouble(dr("MPM"))))}
Else
timeDur = {((Convert.ToDouble(dr("QTY")) / Convert.ToDouble(dr("MPM")) + Convert.ToDouble(dr("Time"))))}
End If
myCurve = myPaneT.AddBar(dr("JOB").ToString & " - " & dr("PRO").ToString(), timeDur, Nothing, BarColor(rowCount))
If MeiSettings.IsGradient = True Then
myCurve.Bar.Fill = New Fill(BarColor(rowCount), Color.White, BarColor(rowCount), 90.0F)
Else
myCurve.Bar.Fill = New Fill(BarColor(rowCount), BarColor(rowCount), BarColor(rowCount), 90.0F)
End If
rowCount += 1
profName = dr("PRO").ToString()
Next
End If
myPaneT.YAxis.MajorTic.IsBetweenLabels = True
myPaneT.YAxis.Type = AxisType.Text
myPaneT.BarSettings.Type = BarType.Stack
myPaneT.BarSettings.Base = BarBase.Y
master.Add(myPaneT)
count += 1
Next
zgc.IsShowPointValues = True
Using g As Graphics = Me.CreateGraphics()
master.SetLayout(g, PaneLayout.SingleColumn)
master.AxisChange(g)
End Using
End Sub
to get control for each GraphPane :
GraphPane temp = zgc.MasterPane.PaneList.ElementAt(ind); //ind => index of the graphpane in zedgraphcontrol
to set static height n width ZedgraphControl :
zgc.Size = new Size(Width,Height);
to set visibility of scrollbar ZedgraphControl :
zgc.IsShowHScrollBar = true;
zgc.IsShowVScrollBar = true;

listview printing

I have found some code using google for listview printing. I modified the code base on my needs. I have some problem if the list view more than one pages. It will not stop counting "Generating Previews" of my document. If I press the cancel it was display the data in multiple pages but the same content.
Any suggestion would greatly appreciated.
Thanks in advance
Here is the code
Public Sub pd_PrintPage(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs)
Dim pd As New PrintDocument
Dim CurrRow As Integer = 0
Dim Ratio As Single = 0
Dim c As ColumnHeader
Dim g As Graphics = e.Graphics
Dim l As Integer = 0 'stores current left
Dim iCount As Integer
Dim f As Font = lsvToPrint.Font
Dim FontBold As New System.Drawing.Font("Microsoft Sans Serif", 10, FontStyle.Bold)
Dim b As Brush = Brushes.Black
Dim currentY As Integer = 0
Dim maxY As Integer = 0
Dim gap As Integer = 5
Dim lvsi As ListViewItem.ListViewSubItem
Dim colLefts(lsvToPrint.Columns.Count) As Integer
Dim colWidths(lsvToPrint.Columns.Count) As Integer
Dim idx As Integer = 0
Dim ii As Integer
Dim lr As RectangleF
e.HasMorePages = False
'Page Settings
Dim PSize As Integer = lsvToPrint.Items.Count
Dim PHi As Double
With pd.DefaultPageSettings
Dim Ps As PaperSize
PHi = PSize * 20 + 350
Ps = New PaperSize("Cust", 800, PHi)
.Margins.Top = 15
.Margins.Bottom = 20
.PaperSize = Ps
End With
Dim sfc As New StringFormat
sfc.LineAlignment = StringAlignment.Center
sfc.Alignment = StringAlignment.Center
'Title
Dim headfont As Font
Dim X1 As Integer
Dim Y As Integer
headfont = New Font("Courier New", 16, FontStyle.Bold)
X1 = pd.DefaultPageSettings.Margins.Left
Y = pd.DefaultPageSettings.Margins.Top + 5
With pd.DefaultPageSettings
e.Graphics.DrawLine(Pens.Black, 0, Y + 70, e.PageBounds.Width, Y + 70)
End With
'Headings
currentY = 100
For Each c In lsvToPrint.Columns
maxY = Math.Max(maxY, g.MeasureString(c.Text, f, c.Width).Height)
colLefts(idx) = l
colWidths(idx) = c.Width
lr = New RectangleF(colLefts(idx), currentY, colWidths(idx), maxY)
If lr.Width > 0 Then g.DrawString(c.Text, FontBold, b, lr, sfc)
l += c.Width
idx += 1
Next
currentY += maxY + gap
g.DrawLine(Pens.Black, 0, currentY, e.PageBounds.Width, currentY)
currentY += gap
'Rows
iCount = lsvToPrint.Items.Count - 1
For ii = CurrRow To iCount
If (currentY + maxY + maxY) > e.PageBounds.Height Then 'jump down another line to see if this line will fit
CurrRow = ii - 1
e.HasMorePages = True
currentY += maxY + gap
Exit For 'does next page
End If
l = 0
maxY = 0
idx = 0
For Each lvsi In lsvToPrint.Items(ii).SubItems
maxY = Math.Max(maxY, g.MeasureString(lvsi.Text, f, colWidths(idx)).Height)
lr = New RectangleF(colLefts(idx), currentY, colWidths(idx), maxY)
If lsvToPrint.Columns(idx).Text <> "Name" Then
If lr.Width > 0 Then g.DrawString(lvsi.Text , f, b, lr, sfc)
Else
If lr.Width > 0 Then g.DrawString(lvsi.Text, f, b, lr)
End If
idx += 1
Next
currentY += maxY + gap
Next
End Sub
Make sure that you compensate the height of the MaxY for the new page. On the first page it's fine, but then when it gets to the next page, CurrentY + MaxY might already be bigger than the height of the page.