Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Detecting a color 1

Status
Not open for further replies.

Scott24x7

Programmer
Jul 12, 2001
2,826
JP
Hi All,
I have an unusual (but really helpful in my application) need to detect a color in an image. The image may be a JPG or a PNG. I need to be able to look at the image (I assume pixel by pixel) and then check if the pixel value matches a specific color value (which I suppose can be expressed as an RGB(R,G,B) value range, or some other).
The problem I have is, I don't know where to start with this. I essentially need to be able to identify 3 colors (Gold, Silver, Bronze), but their exact RGB value is known. Any idea how I can look at an image pixel by pixel in VFP and test for the pixel value = to the color I'm trying to match to?
I've not known VFP to handle image processing very well. I have the EZTwain library as well, but I couldn't find something in it's DIB management that would let me look at it either.
Any guidance would be really great.
Thanks


Best Regards,
Scott
MIET, MASHRAE, CDCP, CDCS, CDCE, CTDC, CTIA, ATS

"Everything should be made as simple as possible, and no simpler."[hammer]
 
There's form.Point() and there's the RGBComp() function in foxtools. See foxtools.chm.

It's less straightforward, as Point only is about form canvas points, you have to check out if you get the pixels RGB value if it's actually not the form itself but an image control or any object having the colored pixel and the form canvas behind it is just the standard background color. I haven't tried, but it surely works when setting the form.picure to get at that pictures pixels colors. It won't be very fast, I'd go for C# or even C++ or perhaps Python for examining an image pixel by pixel. Especially if you think about doing some own OCR development you need something nearer to the "metal" than VFP is.

Bye, Olaf.



Olaf Doschke Software Engineering
 
Hi Olaf,
Interestingly enough, this isn't so complicated in terms of what I need out of it at the end of the day. I have a really strong OCR engine already, but EZTwain and TOCR don't cover this kind of dot-by-dot capability. Mike has put me on to GDIPlusX. I've never used it, but have heard of it. I just downloaded the latest version from GitHub, so will start to muddle my way through that. It seems like the ability will be there.
Speed is important of course, but in my case the image size is fixed, always 450 x 450 pixels, and as soon as I identify which color it has (and I can test each pixel for match to specific value) once I have even one pixel that matches the color, I know I'm good.
I'm using it in conjunction with a drag-and-drop function that already OCRs the image to get text off of it, but I need to make a decision about it from it's color to determine what classification it is, as that isn't stated in the text anywhere. Only identifiable by color.
I've used photoshop to zoom in on them, and the color value is consistent in each image, but it's location can sometimes vary apparently due to some shading issues they have with a fancy font they are using.
I'll give GDIPlusX a whirl, but may be back with some questions there as I have no idea how it works.
Cheers.


Best Regards,
Scott
MIET, MASHRAE, CDCP, CDCS, CDCE, CTDC, CTIA, ATS

"Everything should be made as simple as possible, and no simpler."[hammer]
 
Hi Mike,
So after a bit of reading, tweaking and trying a few things I got a solution that works. It is apparently using the "slow" method, but because of the images I'm using I'm able to narrow it down to just looking at a few pixels in the first 2 or 3 lines (so I end up looking at a block of pixels about 3 x 20, and it exits as soon as it has a match in a range.)

The code is this:
Code:
PROCEDURE UTICHECK
LPARAMETERS lcImage

Set Classlib To Home()+'ffc/_gdiplus.vcx' Additive
oLogoImage = Newobject('gpBitmap',Home()+'ffc/_gdiplus.vcx')
oLogoImage.CreateFromFile(lcImage)

Private x,Y,nColor

lnWidth = oLogoImage.imagewidth
lnHeight = oLogoImage.imageheight
*
lcCertType = ""
*
FOR Y=0 To lnHeight-1
    FOR x=200 To lnwidth-200
*	    WAIT WINDOW NOWAIT "Witdh in pixels: "+TRANSFORM(x)+", height in  pixels :" +TRANSFORM(y)
    	nColor = oLogoImage.GetPixel(x,Y)
    	oColor = Createobject("gpColor",nColor)
		oRed = (oColor.Red)
		oGreen = (oColor.Green)
		oBlue = (oColor.Blue)
		DO CASE
			CASE BETWEEN(oRed,140,240) .AND. BETWEEN(oGreen,100,200) .AND. BETWEEN(oBlue,40,140)
				lcCertType = "Gold"
				EXIT
			CASE BETWEEN(oRed,100,200) .AND. BETWEEN(oGreen,100,200) .AND. BETWEEN(oBlue,100,200)
				lcCertType = "Silver"
				EXIT
		ENDCASE
	NEXT
*
	IF NOT EMPTY(lcCertType)
		EXIT
	ENDIF
NEXT
*
IF EMPTY(lcCertType)
	lcCertType = "Bronze"
ENDIF
*
RETURN lcCertType


Best Regards,
Scott
MIET, MASHRAE, CDCP, CDCS, CDCE, CTDC, CTIA, ATS

"Everything should be made as simple as possible, and no simpler."[hammer]
 
Just notice, you're not using the fine VFPX gdiplusx project, you're using what MS has programmed for gdiplusx usage. It's okay, it obviously works sufficient, but the VFPX implementation of gdi+ is better.
Besides you can use foxtools here and RGBComp() for the little you do you only spare showing the image on a form (thought that could also be an invisible form).

Bye, Olaf.

Olaf Doschke Software Engineering
 
The image is shown on the form in an image class that gets its source from a MEMO field with the filename saved there. But there is no change to the image.
I tried to get GDIPlusX to work, but I got a lot of errors, and couldn't figure out why, so I went with the example that Mike pointed out (that is actually written by Mike Gagnon, Star to MG as well).
I am a little pressed for time at the moment, I figure as I become more familiar with it, I will eventually loop back and convert it to GDI+X when I have a chance.
Though the RGBComp() is something I will look into as well. If I can avoid using GDI at all, I would prefer it.


Best Regards,
Scott
MIET, MASHRAE, CDCP, CDCS, CDCE, CTDC, CTIA, ATS

"Everything should be made as simple as possible, and no simpler."[hammer]
 
About VFPX GdiPlusX usage:

All you do is copy the system.app into your project folder and DO system.app

It initializes and adds to _screen as mainly _screen.system and from there you have all the namespaces you can also see in .NET source code samples, ie System.Drawing maps into _screen.system.drawing

If you use it while you use already instanciated VFPs ffc classes of _gdiplus.vcx you might get errors because GDI+ has some initializations that must only run once. You can't mix two gdi+ libraries for that reason alone, at least they would need to know each other and share a token you get from and keep until you tell to finish your gdi+ session.

I wonder if the ffc classes correctly init and shut down, you may have had errors because of that.

Anyway, the usage is indeed only straightforward, if you're used to this namespace through .NET 2.0 examples. One specific class the project contains making life with it easier is the imgCanvas control combining the VFP image control with gdiplusx, you find that in the gdiplusx.vcx coming with the download.

When you use that instead of the normal VFP image control you automatically have oBmp and oGfx sub-objects in the control, which allow the gdiplusx style of access to an image, eg image.oBmp.GetPixel()

Bye, Olaf.



Olaf Doschke Software Engineering
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top