I'm using this code to calculate the average color of an image but this is not working as desired. The result is inaccurate.
How to find the average color of the image ?
Private Sub btnAvg_Click() Handles btnAvg.Click
Dim x, y As Integer
bmp = New Bitmap(picBox.Tag.ToString)
For y = picBox.Top To picBox.Bottom
For x = picBox.Left To picBox.Right
With bmp.GetPixel(x, y)
totalR = totalR + .R : totalG = totalG + .G : totalB = totalB + .B
End With
Next x
Next y
avgR = totalR / ((picBox.Bottom - picBox.Top) * (picBox.Right - picBox.Left))
avgG = totalG / ((picBox.Bottom - picBox.Top) * (picBox.Right - picBox.Left))
avgB = totalB / ((picBox.Bottom - picBox.Top) * (picBox.Right - picBox.Left))
End Sub
I'm looking for a hi-speed, more than 80% accurate result. This is not a duplicate question as other questions deals with C# only
This should work:
Private Function getAverageColor(ByVal imageFilePath As String) As Color
Dim bmp As New Bitmap(imageFilePath)
Dim totalR As Integer = 0
Dim totalG As Integer = 0
Dim totalB As Integer = 0
For x As Integer = 0 To bmp.Width - 1
For y As Integer = 0 To bmp.Height - 1
Dim pixel As Color = bmp.GetPixel(x, y)
totalR += pixel.R
totalG += pixel.G
totalB += pixel.B
Next
Next
Dim totalPixels As Integer = bmp.Height * bmp.Width
Dim averageR As Integer = totalR \ totalPixels
Dim averageg As Integer = totalG \ totalPixels
Dim averageb As Integer = totalB \ totalPixels
Return Color.FromArgb(averageR, averageg, averageb)
End Function
Averaging colors doesn't make much sense in general. What's the average of hot pink and navy yellow? The way you are calculating it now produces a completely different color.
You'll need to work in a different color space. HSB is an easy one to work with and directly supported by the Color type. Albeit that it doesn't deal with the strongly non-linear color perception of the human eye. Color.GetHue() returns the hue, a value that's directly proportional to the color. You also ought to create a histogram so that the background of the photo doesn't disturb the results too much. Or at least work from the center of photo outwards. Whether that's good enough to detect skin color is fairly doubtful.
You could try this code and see if the results suit you. It reduces the image to a single pixel thumbnail:
Private Function getAverageColor(ByVal imageFilePath As String) As Color
Dim bmp As New Bitmap(imageFilePath)
Dim thumb As New Bitmap(bmp.GetThumbnailImage(1, 1, Nothing, IntPtr.Zero))
Return thumb.GetPixel(0, 0)
End Function
Related
I've implemented the quickshift Quick Shift image segmentation algorithm in vb.net.
Now I'm looking for a C++ or vb.net source code which converts the results of the Quick Shift back into an image.
I tried the following code but the result is not satisfactory.
In the meantime I've implemented it in vb.net myself
but the result is not satisfactory.
Dim qs_obj As VlQS
Dim img_dbl() As Double
Dim result_image As Bitmap
img_dbl = ConvertRGB2LabDouble(Source_Image_PCA)
qs_obj = vl_quickshift_new(img_dbl, Source_Image_PCA.Height, Source_Image_PCA.Width, 3)
vl_quickshift_process(qs_obj)
vl_quickshift_set_kernel_size(qs_obj, 10)
vl_quickshift_set_max_dist(qs_obj, 10)
result_image = CType(Source_Image_PCA.Clone, Bitmap)
For y As Integer = 0 To Source_Image_PCA.Height - 1
For x As Integer = 0 To Source_Image_PCA.Width - 1
Dim pixelindex As Integer = qs_obj.parents(y * Source_Image_PCA.Width + x)
Dim col As Integer = pixelindex Mod (Source_Image_PCA.Width)
Dim row As Integer = pixelindex \ Source_Image_PCA.Width
Dim pixel_val As Color
pixel_val = Source_Image_PCA.GetPixel(col, row)
result_image.SetPixel(x, y, pixel_val)
Next
Next
picImageSpecialFnc.Image = result_image
I'm using Logo right now and i'm making a project and basically i want to turn your recorded voice into something visual, only problem is when i go to find code it re that works it requires 1: A picture box and 2: to manually grab the sound .wav file and place it. I already made code to record my voice and to make it into a .Wav file and i already have code to visualize it, just when i run it it appears as a thick square of lines rather than the example i shown. Note: I'm not drawing into a picturebox, i'm drawing directly into the Form by using g.drawline(bleh,bleh,bleh,bleh).
(Example: http://static1.1.sqspcdn.com/static/f/335152/16812948/1330286658510/76_dsc3616.jpeg?token=R1zPNnr9PAoB3WvnDxfFFFvzkMw%3D )
The code im trying to run:
Public Sub DrawSound(x As Integer, y As Integer)
Dim samplez As New List(Of Short)
Dim maxamount As Short
Dim pic As New Bitmap(x, y)
Dim ratio As Integer = (samplez.Count - 1) / (y - 1) 'If there are 10000 samples and 200 pixels, this would be every 50th sample is shown
Dim halfpic As Integer = (x / 2) 'Simply half the height of the picturebox
GC.Collect()
Dim wavefile() As Byte = IO.File.ReadAllBytes("C:\Users\" & Environ$("Username") & "\Documents\Sounds\Mic.wav")
GC.Collect()
Dim memstream As New IO.MemoryStream(wavefile)
Dim binreader As New IO.BinaryReader(memstream)
Dim ChunkID As Integer = binreader.ReadInt32()
Dim filesize As Integer = binreader.ReadInt32()
Dim rifftype As Integer = binreader.ReadInt32()
Dim fmtID As Integer = binreader.ReadInt32()
Dim fmtsize As Integer = binreader.ReadInt32()
Dim fmtcode As Integer = binreader.ReadInt16()
Dim channels As Integer = binreader.ReadInt16()
Dim samplerate As Integer = binreader.ReadInt32()
Dim fmtAvgBPS As Integer = binreader.ReadInt32()
Dim fmtblockalign As Integer = binreader.ReadInt16()
Dim bitdepth As Integer = binreader.ReadInt16()
If fmtsize = 18 Then
Dim fmtextrasize As Integer = binreader.ReadInt16()
binreader.ReadBytes(fmtextrasize)
End If
Dim DataID As Integer = binreader.ReadInt32()
Dim DataSize As Integer = binreader.ReadInt32()
samplez.Clear()
For i = 0 To (DataSize - 3) / 2
samplez.Add(binreader.ReadInt16())
If samplez(samplez.Count - 1) > maxamount Then 'Using this for the pic
maxamount = samplez(samplez.Count - 1)
End If
Next
For i = 1 To x - 10 Step 2 'Steping 2 because in one go, we do 2 samples
Dim leftdata As Integer = Math.Abs(samplez(i * ratio)) 'Grabbing that N-th sample to display. Using Absolute to show them one direction
Dim leftpercent As Single = leftdata / (maxamount * 2) 'This breaks it down to something like 0.0 to 1.0. Multiplying by 2 to make it half.
Dim leftpicheight As Integer = leftpercent * x 'So when the percent is tied to the height, its only a percent of the height
g.DrawLine(Pens.LimeGreen, i, halfpic, i, leftpicheight + halfpic) 'Draw dat! The half pic puts it in the center
Dim rightdata As Integer = Math.Abs(samplez((i + 1) * ratio)) 'Same thing except we're grabbing i + 1 because we'd skip it because of the 'step 2' on the for statement
Dim rightpercent As Single = -rightdata / (maxamount * 2) 'put a negative infront of data so it goes down.
Dim rightpicheight As Integer = rightpercent * x
g.DrawLine(Pens.Blue, i, halfpic, i, rightpicheight + halfpic)
Next
End Sub
X and Y is the middle of the form. And i also would link where i got the code but i forgot where and also, i modified it in attempt to run it directly into he form rather than a picturebox. It worked sorta haha (And there is so many unused dims but all i know is, once i remove one none of the code works haha) So could anyone help?
I was tasked today after creating a program to Add watermarks to also create one to remove that same watermark.
My thoughts are that it is now part of the image and can't be removed so easily.
Is this accurate or is the actually a way? ( that doesnt take 10 years)
thanks for any hints
Here is my code to add the watermarks:
Dim watermark_bm As Bitmap = Global.AnchorAuditor.My.Resources.Logo_White
Dim watermark_bm2 As Bitmap = Global.AnchorAuditor.My.Resources.CLS_Logo_White_Engineering
'watermark_bm2.MakeTransparent()
' WATERMARK IMAGE 1 - AA
Using str As Stream = File.OpenRead(s)
Dim or_bm As Bitmap = Image.FromStream(str)
'''''''''''''''''''''''''START IMAGE 1''''''''''''''''''''''''''
or_bm.SetResolution(20, 20)
Dim x1 As Integer = or_bm.Width - 300
Dim Y As Integer = or_bm.Height - 300
Const ALPHA As Byte = 128
' Set the watermark's pixels' Alpha components.
Dim clr As Color
For py As Integer = 0 To watermark_bm.Height - 1
For px As Integer = 0 To watermark_bm.Width - 1
clr = watermark_bm.GetPixel(px, py)
watermark_bm.SetPixel(px, py, _
Color.FromArgb(ALPHA, clr.R, clr.G, clr.B))
Next px
Next py
' Set the watermark's transparent color.
watermark_bm.MakeTransparent(watermark_bm.GetPixel(0, _
0))
' Copy onto the result image.
Dim gr As Graphics = Graphics.FromImage(or_bm)
gr.DrawImage(watermark_bm, x1, Y)
'''''''''''''''''''''''''END IMAGE 1 START IMAGE 2''''''''''''''''''''''''''
or_bm.SetResolution(60, 60)
Dim x2 As Integer = 75
Dim Y1 As Integer = 75
Const ALPHA1 As Byte = 128
' Set the watermark's pixels' Alpha components.
Dim clr1 As Color
For py As Integer = 0 To watermark_bm2.Height - 1
For px As Integer = 0 To watermark_bm2.Width - 1
clr1 = watermark_bm2.GetPixel(px, py)
watermark_bm2.SetPixel(px, py, _
Color.FromArgb(ALPHA1, clr1.R, clr1.G, clr1.B))
Next px
Next py
' Set the watermark's transparent color.
watermark_bm2.MakeTransparent(watermark_bm2.GetPixel(0, _
0))
' Copy onto the result image.
Dim gr1 As Graphics = Graphics.FromImage(or_bm)
gr1.DrawImage(watermark_bm2, x2, Y1)
''''''''''''''''''''''''END IMAGE 2'''''''''''''''''''''''''''
or_bm.Save(s & "deleteme.jpg", _
System.Drawing.Imaging.ImageFormat.Jpeg)
End Using
You're correct - adding a watermark is far easier than removing it. The standard approach is to keep a copy of the original someplace and use that instead of trying to manipulate the image afterwards.
Is there any way to attribute a code for every color, and be able to read them? Programatically I mean.
My target is to convert an image into code, then convert it back to image.
Each color has 4 fields (For some images, you only have 3 fields with meaningful information)
These fields include:
Alpha (A) (This represents opacity of the pixel)
Red (R) (Red intensity)
Green (G) (Green intensity)
Blue (B) (Blue intensity)
What you would do is read them and generate a code string for each one by concatenating the values to one another.
This can most likely be considered pseudo-code as I did not check if it compiles, but you should be doing something along the lines of this.
Dim pixelColor As Color
Dim image As BitMap = New BitMap("your_image.png")
Dim a As String
Dim r As String
Dim b As String
Dim g As String
Dim fileString As New StringBuilder()
fileString.AppendLine(image.Size.Width.ToString())
fileString.AppendLine(image.Size.Height.ToString())
' Loop over all pixels
For y As Integer = 0 To image.Size.Height - 1
For x As Integer = 0 To image.Size.Width - 1
pixelColor = image.GetPixel(x, y)
' get ARGB values as strings
a = pixelColor.A.ToString()
r = pixelColor.R.ToString()
g = pixelColor.G.ToString()
b = pixelColor.B.ToString()
' Append the colors, one pixel per line
fileString.AppendLine(a & " " & r & " " & g & " " & b)
Next
Next
Using file As New StreamWriter("image_data.txt")
outfile.Write(fileString.ToString())
End Using
Again, this probably doesn't compile. (I don't have a compiler with me at the moment)
edit:
I realized that the width and height need to be stored as well.
As for reading the file:
Dim file As System.IO.StreamReader
file = File.OpenText("text_file.txt")
Dim width As Integer = Convert.ToInt32(file.ReadLine)
Dim height As Integer = Convert.ToInt32(file.ReadLine)
Dim image As BitMap = New BitMap(width, height)
Dim currentX As Integer = 0
Dim currentY As Integer = 0
Do Until file.EndOfStream
Dim line As String = file.ReadLine
Dim valueArray(4) As String = line.Split(" ")
Dim a As Integer = Convert.ToInt16(valueArray(0))
Dim r As Integer = Convert.ToInt16(valueArray(1))
Dim g As Integer = Convert.ToInt16(valueArray(2))
Dim b As Integer = Convert.ToInt16(valueArray(3))
image.SetPixel(currentX, currentY, Color.FromArgb(a, r, g, b))
currentX = currentX + 1
If currentX == width Then
currentX = 0
currentY = currentY + 1
If currentY == height Then
Exit Do ' We're done here.
End If
End If
Loop
' At this point, you'll have a BitMap with all the pixels set.
Again, consider this pseudo-code.
each color is actually a ARGB color code just get integer value
Dim myColor As Color = Color.Red
Dim Code As Integer = myColor.ToArgb()
Dim myColorBack As Color = Color.FromArgb(Code)
Having a problem with the amount of memory being used going up and up, and expanding until there is no memory left. I'm using the GHeat.Net plugin to build images. Here is the full code:
Dim pm As New gheat.PointManager()
Dim g As Graphics
Dim startZoom As Integer = 2
Dim maxZoom As Integer = 17
gheat.Settings.BaseDirectory = "C:\\gheatWeb\\__\\etc\\"
pm.LoadPointsFromFile("C:\\points.txt")
For zoom As Integer = startZoom To maxZoom
Dim startX As Integer = 0
Dim startY As Integer = 0
Dim maxX As Integer = 2 ^ zoom
Dim maxY As Integer = 2 ^ zoom
For x As Integer = startX To maxX
For y As Integer = startY To maxY
Dim filename As String = "C:\\images\\" + zoom.ToString + "\\x" + x.ToString + "y" + y.ToString + "zoom" + zoom.ToString + ".gif"
gheat.GHeat.GetTile(pm, "classic", zoom, x, y).Save(filename, System.Drawing.Imaging.ImageFormat.Gif)
Next
Next
Next
For some reason, when I hit the for loops, the amount of memory used just goes up and up and up, until it hits a ceiling. Even then, the program keeps running, but the amount of memory doesn't go up. The program generates fine at 20Mb, so I can't figure out why it just keeps going up.
I've also tried GC.Collect at the end of the innermost loop, to no avail. Any ideas?
GHeat.GetTile returns a Bitmap which must be disposed.
Also, there's no need to escape paths like that in VB.
For x As Integer = startX To maxX
For y As Integer = startY To maxY
Dim filename As String = String.Format("C:\images\{0}\x{1}y{2}zoom{3}.gif", zoom, x, y, zoom)
Using img = gheat.GHeat.GetTile(pm, "classic", zoom, x, y)
img.Save(filename, System.Drawing.Imaging.ImageFormat.Gif)
End Using
Next
Next