Results 1 to 15 of 15

Thread: Convertin colors to more simple colors in an image.

  1. #1

    Thread Starter
    New Member
    Join Date
    Feb 2004
    Posts
    15

    Convertin colors to more simple colors in an image.

    Hi all,

    I am developing a project and I need your advices.

    We are manufacturing marble. Some people take photographs of marbles with digital camera and send it to us.

    Until now, we open all images and write which kind of marble.
    Every marble has its own characteristic.

    For example one's characteristic is

    white background and black vessels on it

    the other's

    orange background and grey vessels on it.

    Now I trying to recognize marble kind with visual basic.

    This will my future steps,

    1.(which I don't know how to do it) Convert all colors to an most approximate simple color. For example
    Lightskyblue= blue
    Lightsteelblue= blue
    .
    .
    .
    Lightyellow = yellow
    Wheat= yellow
    .
    .
    .

    How can I do it with rgb or hex values. (Or it is possible to use color palettes?)

    2. (I can do it) Count every color in new image. Then sort them in most repetition in descending order. Then pick 2 or 3 top colors to define which kind of marble.


    Could you please help, or have different advices?

    Thank in advance.
    Last edited by googleelgoog; Feb 26th, 2004 at 05:54 AM.

  2. #2
    Retired G&G Mod NoteMe's Avatar
    Join Date
    Oct 2002
    Location
    @ Opera Software
    Posts
    10,190
    I am not good with palettes, so I can't help you there...maybe someone else can.

    But the other way you could use the GetPixel API to get the color from the picture in a picturebox or something. If you do that all over the image you can check what color it is. You have to make a function that defines what is

    Lightskyblue= blue
    Lightsteelblue= blue

    and so on. If you look how much Red and Green and Blue color there is from the result, you should make a conclusion if it is Blue, and what kind of blue it is.


    The biggest problem here is if they take a picture and get more then the floor on the picture. Then your function will add that too. But not sure if that is a problem for you.....

  3. #3
    transcendental analytic kedaman's Avatar
    Join Date
    Mar 2000
    Location
    0x002F2EA8
    Posts
    7,221
    It depends on your choice of "simple" palette. There are different ways of calculating distance between colours but depending on the method you can arrive at the closest colour. Easiest would be to use the ones used on your display: black, white, red, green, blue, yellow, magenta and cyan
    Use
    writing software in C++ is like driving rivets into steel beam with a toothpick.
    writing haskell makes your life easier:
    reverse (p (6*9)) where p x|x==0=""|True=chr (48+z): p y where (y,z)=divMod x 13
    To throw away OOP for low level languages is myopia, to keep OOP is hyperopia. To throw away OOP for a high level language is insight.

  4. #4
    Frenzied Member cyborg's Avatar
    Join Date
    May 2000
    Location
    Sweden
    Posts
    1,755
    try doing something like this:

    loop through all pixels and then check the rgb values

    if red > 150 and green < 100 and blue < 100 then
    'this color is probably red
    etc...

    you should change those values so that it gives the best result and add alot of more ifs.
    Check out the FAQ and do a search before you post.
    My tutorials: Anti-Alias Pixels, Accurate Game Loop, Resource File

  5. #5
    Fanatic Member
    Join Date
    Oct 1999
    Location
    England
    Posts
    982
    I have been looking to do the same thing.

    After looking round the internet for days and including lots of forums I have come to the same conclusion as cyborg. looping through each pixel.

    However I don't like the idea of comparing the Red, Green and Blue value individually of every pixel.

    Is it possible to convert the RGB value into something for easier comparison, say a single long value. You can then create a lookup table with the upper and lower bounds for red.

    Does anyone know of a way to convert the RGB value into a single value?


    Things I do when I am bored: DotNetable

  6. #6
    Retired G&G Mod NoteMe's Avatar
    Join Date
    Oct 2002
    Location
    @ Opera Software
    Posts
    10,190
    Can't you do something like

    VB Code:
    1. Dim lColor as Long
    2.  
    3. lColor = RGB(lRed, lGreen, lBlue)

  7. #7
    Retired G&G Mod NoteMe's Avatar
    Join Date
    Oct 2002
    Location
    @ Opera Software
    Posts
    10,190
    I even looked it up for you...

    Returns aLong whole number representing an RGB color value.

    Syntax

    RGB(red, green, blue)

    The RGB function syntax has thesenamed arguments:

    Part Description
    red Required; Variant (Integer). Number in the range 0–255, inclusive, that represents the red component of the color.
    green Required; Variant (Integer). Number in the range 0–255, inclusive, that represents the green component of the color.
    blue Required; Variant (Integer). Number in the range 0–255, inclusive, that represents the blue component of the color.


    Remarks

    Applicationmethods andproperties that accept a color specification expect that specification to be a number representing an RGB color value. An RGB color value specifies the relative intensity of red, green, and blue to cause a specific color to be displayed.

    The value for anyargument to RGB that exceeds 255 is assumed to be 255.

    The following table lists some standard colors and the red, green, and blue values they include:

    Color Red Value Green Value Blue Value
    Black 0 0 0
    Blue 0 0 255
    Green 0 255 0
    Cyan 0 255 255
    Red 255 0 0
    Magenta 255 0 255
    Yellow 255 255 0
    White 255 255 255


  8. #8
    Fanatic Member
    Join Date
    Oct 1999
    Location
    England
    Posts
    982
    What more could I ask.

    Thats brilliant.


    Things I do when I am bored: DotNetable

  9. #9
    Ex-Super Mod'rater Electroman's Avatar
    Join Date
    Sep 2000
    Location
    Newcastle, England
    Posts
    4,349
    Once a RGB color has been put in a Long theres not much you can do to compare it. For example if the Red part is increased by 1 the chnage is way different to just adding one onto the Blue. This is because the Bits are stored like:

    RRRR RRRR GGGG GGGG BBBB BBBB

    It could be an idea to just add up the values of all the Reds for every pixel, same for greens & blues then take an average of them all. This would require a rather large number though if the image is big so I dont know if a Long would be big enough to hold all the values of a color from a image.

    You might find it useful for your program to blur the image before it does anything with it as well. I find this useful because if your looking for trends it will be too picky about it not being exact if you dont blur it. Bluring wont effect finding the average color though (Unless you look for the most popular color then it will).

    Theres my two cents .
    When your thread has been resolved please edit the original post in the thread ()
    and amend "-[RESOLVED]-" to the end of the title and change the icon to , Thank you.

    When posting Code use the [VBCode]Code Here[/VBCode] tags to be able to use the code highlighting.

  10. #10
    So Unbanned DiGiTaIErRoR's Avatar
    Join Date
    Apr 1999
    Location
    /dev/null
    Posts
    4,111
    There are palette APIs which would allow you to scan an image, return unique palette entries(then based on your pre-defined RGB entries in the palette replace it with a color matching it.)

    Another way would be to convert RGB into HSL(sometimes called HSV... hue(color),sat.(how 'rich' the color is)lum.(brightness)).

    Then you'd take the values, select case them using ranges, and come out with a fairly good description of the marble(atleast color-wise). The hard part would be describing things such as the 'eye' or vessels.

  11. #11
    Fanatic Member
    Join Date
    Oct 1999
    Location
    England
    Posts
    982
    Originally posted by DiGiTaIErRoR
    There are palette APIs which would allow you to scan an image, return unique palette entries(then based on your pre-defined RGB entries in the palette replace it with a color matching it.)

    Another way would be to convert RGB into HSL(sometimes called HSV... hue(color),sat.(how 'rich' the color is)lum.(brightness)).

    Then you'd take the values, select case them using ranges, and come out with a fairly good description of the marble(atleast color-wise). The hard part would be describing things such as the 'eye' or vessels.
    Do you know of any examples of these methods.


    Things I do when I am bored: DotNetable

  12. #12
    So Unbanned DiGiTaIErRoR's Avatar
    Join Date
    Apr 1999
    Location
    /dev/null
    Posts
    4,111
    Public Type PALETTEENTRY
    peRed As Byte
    peGreen As Byte
    peBlue As Byte
    peFlags As Byte
    End Type

    Public Type LOGPALETTE
    palVersion As Integer
    palNumEntries As Integer
    palPalEntry(255) As PALETTEENTRY
    End Type

    'types for palette creation

    Private Declare Function CreatePalette Lib "gdi32" (lpLogPalette As LOGPALETTE) As Long

    Is used to create a logical palette.

    Public Declare Function GetNearestPaletteIndex Lib "gdi32" (ByVal hPalette As Long, ByVal crColor As Long) As Long

    Will return the palette index of the nearest color to crColor in hPalette.

    You'll then have to declare some memory types...

    Public Pal As LOGPALETTE
    Public hPal As Long 'handle to the palette(will be set = createpalette)

    Now the code...
    VB Code:
    1. Pal.palNumEntries = 256
    2. Pal.palVersion = &H300 'defines our palette entries and type of palette
    3.  
    4. 'define the colors in the palette
    5. Pal.palpalEntry(x).peRed = 1
    6. Pal.palpalEntry(x).peGreen = 2
    7. Pal.palpalEntry(x).peBlue = 3
    8.  
    9. 'When you've set the colors in the palette, you now do:
    10.  
    11. hPal = CreatePalette(Pal)
    12.  
    13. x = GetNearestPaletteIndex(hPal, somecolor)
    14.  
    15. 'now to retieve the palette's 'approximate' of  somecolor
    16. r = Pal.palpalEntry(x).peRed
    17. g = Pal.palpalEntry(x).peGreen
    18. b = Pal.palpalEntry(x).peBlue

    A simple Google search should provide a method to convert HSL(HSV)<->RGB. Or try PSC.
    Last edited by DiGiTaIErRoR; Apr 18th, 2004 at 05:54 AM.

  13. #13
    Fanatic Member
    Join Date
    Oct 1999
    Location
    England
    Posts
    982
    DiGiTaIErRoR, Looking at your code there are a few things I am unsure of.[list=1][*]Where does modprop come from?
    hPal = CreatePalette(modProp.Pal)
    [*]I noticed you declared 255 palette entries but only initialised the RGB of one entry. Can I have any number of entries, 10,100 or 201.[/list=1]
    I looked on www.allapi.net for additional help but could not find GetNearestPaletteIndex.


    Things I do when I am bored: DotNetable

  14. #14
    So Unbanned DiGiTaIErRoR's Avatar
    Join Date
    Apr 1999
    Location
    /dev/null
    Posts
    4,111
    A module, lol.

    Yup, you can pick any number(1-256).

    palPalEntry(255) As PALETTEENTRY = 0 to 255 or 256 total

  15. #15
    Retired G&G Mod NoteMe's Avatar
    Join Date
    Oct 2002
    Location
    @ Opera Software
    Posts
    10,190
    Originally posted by davidrobin

    I looked on www.allapi.net for additional help but could not find GetNearestPaletteIndex.

    From MSDN (not sure if it can help you)...


    GetNearestPaletteIndex
    The GetNearestPaletteIndex function retrieves the index for the entry in the specified logical palette most closely matching a specified color value.

    UINT GetNearestPaletteIndex(
    HPALETTE hpal, // handle of logical color palette
    COLORREF crColor // color to be matched
    );

    Parameters
    hpal
    Handle to a logical color palette.
    crColor
    Specifies a color to be matched.
    Return Values
    If the function succeeds, the return value is the index of an entry in a logical palette.

    If the function fails, the return value is CLR_INVALID.

    Windows NT: To get extended error information, callGetLastError.

    Remarks
    An application can determine whether a device supports palette operations by calling the GetDeviceCaps function and specifying the RASTERCAPS constant.

    If the given logical palette contains entries with the PC_EXPLICIT flag set, the return value is undefined.

    QuickInfo
    Windows NT: Requires version 3.1 or later.
    Windows: Requires Windows 95 or later.
    Windows CE: Requires version 2.0 or later.
    Header: Declared in wingdi.h.
    Import Library: Use gdi32.lib.



Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width