Modifying color Images to help with segmentation
(Originally posted by Earl Sanford on 1/11/2008)
I
am having some difficulty in putting together a basic macro that looks
at each pixel in an TIF image to determine what color it should be
called. All of the examples I have found looking through the help
screens and online deal with grayscale images. Hopefully one of you can
help me figure out how to modify a color image.
What I want to do is
compare the red, green and blue components of a pixel and change the
value of these components so I will have an image that is easier to
segment - basically a four color image. Below I have attached a portion
of the macro I have been working on. The images I am running this on are
1280 x 1024 TIF images.
If anyone can figure out what I am doing
wrong, or has a better idea as to how to segment color images that vary
widely in color range, I would greatly appreciate hearing from you.
Sub Modify_TIF()
Dim I As Integer
Dim j As Integer
Dim Red_Pixel As Integer
Dim Green_Pixel As Integer
Dim Blue_Pixel As Integer
Dim ImBufByte As Byte
Dim Reg As RECT
Reg.Left=0
Reg.top=0
Reg.Right=3840
Reg.bottom=3072
ReDim ImBuf(Reg.Left To Reg.Right,Reg.top To Reg.bottom) As Integer
ret=IpDocGetArea(DOCSEL_ACTIVE,Reg,ImBuf(Reg.Left,Reg.top),0)
For j = 1 To 3072
For I = 1 To 3840
Red_Pixel=ImBuf(I, j)
Green_Pixel=ImBuf(I+1, j)
Blue_Pixel=ImBuf(I+2, j)
If Blue_Pixel > Red_Pixel Then
ImBuf(I, j)=100
ImBuf(I+1, j)=100
ImBuf(I+2, j)=245
GoTo next_pixel
End If
If Red_Pixel > Blue_Pixel Then
If Green_Pixel > Blue_Pixel Then
ImBuf(I, j)=200
ImBuf(I+1, j)=160
ImBuf(I+2, j)=100
GoTo next_pixel
End If
ImBuf(I, j)=200
ImBuf(I+1, j)=100
ImBuf(I+2, j)=160
GoTo next_pixel
End If
'If pixel not red, yellow or blue - make it "black"
ImBuf(I, j)=10
ImBuf(I+1, j)=10
ImBuf(I+2, j)=10
next_pixel:
I=I+3
Next I
j=j+3
Next j
ret=IpDocPutArea(DOCSEL_ACTIVE,Reg,ImBuf(Reg.Left,Reg.top),0)
' refresh the display of the active document.
ret = IpAppUpdateDoc(DOCSEL_ACTIVE)
End Sub
Comments
(Originally posted by YuriG on 1/11/2008)
The ranges on the IpDocGetArea & IpDocPutArea are hard to get right. The dimensions should look like:
ReDim ImBuf(Reg.Left*3 To (Reg.Right*3+2),Reg.top To Reg.bottom) As Integer
The width needs be multiplied by a factor of 3, because it needs 3 numbers for each pixel. Of course, this changes the range of your for loops, too:
For j = Reg.top To Reg.bottom
For I = Reg.Left*3 To (Reg.Right)*3 Step 3
The "Step 3" makes sure that "I" increments by 3 on every loop.
Finally, since the "Next" command causes the I & j variables to be incremented, so you don't need the I=I+3 & j=j+3.
A way to avoid accessing the individual pixel data would be to:
- Use the Process | Color Channel command to extract each color
- Use Process | Operations to mathematically subtract each of the colors from each other
- Use Process | Segmentation to "mask" any values > 0
- Use the segmentation window to "Create Preview Image",
. . . using the "Class Color on Black" color option
. . . changing the "Class Color" (by clicking on the color square right next to the [New] and [Del] buttons)
- Adding all of the created "Preview" images together
This can work, BUT it's a lot more steps than just directly access the pixel data, like you're doing in your code. Also, it uses a lot more memory, since it opens up a bunch of copies of the image.
(Originally posted by KevinR on 1/14/2008)
I would endorse following the previous suggestion - Extract the color channels and perform whatever math you wish on those.It will use more memory, but a few copies of 1280x1024 images doesn't add up to much, and image operation commands will be _much_ faster than macro based pixel operations. Operations such as MIN and MAX, multiplying an image by 255 to turn it into a mask (any non-zero value becomes 255, zero values remain zero), and fairly simple combinations should give you your results.