Automating Image Analysis

Hi,
I have to extract RGB profiles from n number of images, and for a single image analysis, and I've written a code that looks like the following:

Function RGB_Profile()
    ImageLineProfile/P=-2 srcWave=image, xWave=coord_x, yWave=coord_y, width=1  //Get R,G,B line profiles from a ROI in an image using coordinates "x_coord", "y_coord" obtained from graph marquee
    Make/N=(numpnts(M_ImageLineProfile)/3) pixel_x  //M_ImageLineProfile contains 3 columns of data for R, G, B. make a wave with the same number of points required for position calibration
    Redimension/N=(numpnts(M_ImageLineProfile)) M_ImageLineProfile  //Combine 3 columns into 1 column
    Duplicate/R=(0,(numpnts(pixel_x)-1)) M_ImageLineProfile, profileR       //extract profile R from M_ImageLineProfile
    Duplicate/R=((numpnts(pixel_x)), (numpnts(pixel_x)*2-1)) M_ImageLineProfile profileG        //extract profile G from M_ImageLineProfile
    Duplicate/R=((numpnts(pixel_x))*2, (numpnts(pixel_x)*3-1)) M_ImageLineProfile profileB  //extract profile B from M_ImageLineProfile
    pixel_x=x+(coord_x[0])  //calibrate actual pixel position with no. of rows in profiles R, G, and B
    Display profileR profileG profileB vs pixel_x
    ModifyGraph rgb(profileG)=(0,65280,0),rgb(profileB)=(0,0,65280)


I have already loaded n number of images named, image1, image2 and etc., and I'm trying to automate this analysis for all images in sequence, and I was wondering what the simplest way is to do this.

Thank you for the help!
If you are going to apply a function to multiple data sets you should start by modifying your code so that the various waves are passed as function parameters. In the case of your example above it would look something like:
Function  RGB_Profile(imageWave,coord_x,coord_y)
Wave imageWave,coord_x,coord_y

...

End


Next, you should ask yourself if you really want to display the results or just store them for display later. In both cases your function should be modified so that the "output" waves (profileR, profileG, profileB and pixel_x) are not overwritten by subsequent calls to your function. One way to accomplish this is to store the result of each run in a dedicated data folder:


Function  RGB_Profile(imageWave,coord_x,coord_y)
Wave imageWave,coord_x,coord_y

    DFREF saveDFR = GetDataFolderDFR()   // Save old df
    NewDataFolder/O/S someDFName        // create new df

        ...                     // do your work here
       
    SetDataFolder saveDFR           // and restore
End


The choice of someDFName needs to be unique. One way to generate it is:
String dfName="folder"+num2str(index)


where index is a count for the image that you are processing.

The next part to handle is your "image sequence". If your images are already loaded into the experiment you could create a string list using WaveList() from which you sequentially pick up an image for processing. If your images are not already loaded (say they are stored on a disk file) you can use IndexedFile() (see, for example http://www.igorexchange.com/node/537).

Finally, your code for extracting the three components is more complex than necessary:
    Redimension/N=(numpnts(M_ImageLineProfile)) M_ImageLineProfile  //Combine 3 columns into 1 column
    Duplicate/R=(0,(numpnts(pixel_x)-1)) M_ImageLineProfile, profileR       //extract profile R from M_ImageLineProfile
    Duplicate/R=((numpnts(pixel_x)), (numpnts(pixel_x)*2-1)) M_ImageLineProfile profileG        //extract profile G from M_ImageLineProfile
    Duplicate/R=((numpnts(pixel_x))*2, (numpnts(pixel_x)*3-1)) M_ImageLineProfile profileB  //extract profile B from M_ImageLineProfile


I'd replace it with:
    Wave M_ImageLineProfile
    MatrixOP/O profileR=col(M_ImageLineProfile,0)
    MatrixOP/O profileG=col(M_ImageLineProfile,1)
    MatrixOP/O profileB=col(M_ImageLineProfile,2)


I hope this helps,

A.G.
WaveMetrics, Inc.
Thank you. I've modified the code per your suggestion, but I still seem to have a problem while trying to execute the function.

Function RGB_Profile()
    String list=ImageNameList("", ";")
    String imageName
    String currentWave
    Variable index = 0
    Wave coord_x, coord_y
    do
        imageName = StringFromList(index, list)
        if(strlen(imageName) == 0)
            break       // No more images
        endif
       
        String DFName = "image"+num2str(index)
        DFREF saveDFR = GetDataFolderDFR()      // Get reference to current data folder
        NewDataFolder/O/S $DFName       // Make folder named image"i"
           
            Variable i = 0
            do
            currentWave = StringFromList(i, list)
            if(strlen(currentWave) == 0)        // No more images
                break
            endif
            String imageWave = "image"+num2str(i)
            Wave w = $imageWave
            ImageLineProfile/P=-2 xWave=root:coord_x, yWave=root:coord_y, srcWave=$imageWave, width=1       // ImageLineProfile for image"i"
            Make/N=(numpnts(M_ImageLineProfile)/3) pixel_x
            Wave M_ImageLineProfile
            MatrixOP/O profileR=col(M_ImageLineProfile,0)
            MatrixOP/O profileG=col(M_ImageLineProfile,1)
            MatrixOP/O profileB=col(M_ImageLineProfile,2)
            pixel_x=x+(coord_x[0])
            Display profileR profileG profileB vs pixel_x
            ModifyGraph rgb(profileG)=(0,65280,0),rgb(profileB)=(0,0,65280)
            i += 1
        while (1)
        index += 1
    while (1)
    SetDataFolder root:     // Set current data folder back to root folder
End


I've already loaded my images (named image0, image1, etc.) and I will be using the same coord_x & coord_y (in the root folder) for all images.
When I try to execute the function, I get the following error message:
"While executing ImageLineProfile, the following error occurred: One or more of the input waves are not supported."
I think "srcwave=$imageWave" is causing the problem, but I don't seem to be able to figure out what's wrong.
Do you have any idea why?
Thank you for the help!
isk8 wrote:
"While executing ImageLineProfile, the following error occurred: One or more of the input waves are not supported."
I think "srcwave=$imageWave" is causing the problem, but I don't seem to be able to figure out what's wrong.
Do you have any idea why?


This error can occur for two reasons:
1) Igor didn't find one or more of the x, y, or src waves that you specified (for example, ImageLineProfile was called with a NULL srcWave wave).
2) One or more of the x, y, z waves is a text wave (contains text instead of numbers).

The second option is unlikely. A potential culprit is indeed that Igor cannot find the wave in the srcwave=$imageWave statement.

I would go about diagnosing this using the debugger (execute DisplayHelpTopic "The Debugger" if this extremely valuable tool doesn't ring any bells). Right-click somewhere in your procedure window, and select "Enable Debugger" if it isn't checked already. Next click in the margin next to the Wave w = $imageWave line, run your function, and watch what happens when you execute the statement (using the 'step over' instruction in the upper left-hand side of the debugger window). Is w NULL after this statement executes? Then that is your problem.

The debugger usually is your best friend in situations such as these.
741 is right as usual: the debugger is indeed your best bet at this point. A closer look at your code makes me wonder what you are trying to do. In particular:

isk8 wrote:


            Variable i = 0
            do
            currentWave = StringFromList(i, list)  /
            if(strlen(currentWave) == 0)        // No more images
                break
            endif
            String imageWave = "image"+num2str(i)
            Wave w = $imageWave
            ImageLineProfile/P=-2 xWave=root:coord_x, yWave=root:coord_y, srcWave=$imageWave, width=1       // ImageLineProfile for image"i"



1. What is the role of currentWave?
2. If you already have imageName why are you executing:
 Wave w = $imageWave
and not
 Wave w = $imageName

Also, you may find it better to use Wave/Z and then test:
if(WaveExists(w))
    ImageLineProfile/P=-2 xWave=root:coord_x, yWave=root:coord_y, srcWave=w, width=1        // ImageLineProfile for image"i"
endif


I hope this helps,

A.G.
WaveMetrics, Inc.
Thanks for the advice.

741 wrote:

This error can occur for two reasons:
1) Igor didn't find one or more of the x, y, or src waves that you specified (for example, ImageLineProfile was called with a NULL srcWave wave).
2) One or more of the x, y, z waves is a text wave (contains text instead of numbers).


As you mentioned, I also think 2) is unlikely because I've already defined them as waves. Also, if I just type in "ImageLineProfile" function with image0 instead of $imageWave, it works.

741 wrote:

Is w NULL after this statement executes? Then that is your problem.

The debugger usually is your best friend in situations such as these.


I've tried this, but w is not NULL. In fact, it is image0, which is the correct src wave.
This is really strange, because as mentioned above, if I manually type in image0 in the place of $imageWave the function works.
But, if image0 is replaced with $imageWave, the function keeps on giving me the same error.

I'd really appreciate if there are any other suggestions.
Thank you.
isk8 wrote:

I've tried this, but w is not NULL. In fact, it is image0, which is the correct src wave.
This is really strange, because as mentioned above, if I manually type in image0 in the place of $imageWave the function works.
But, if image0 is replaced with $imageWave, the function keeps on giving me the same error.
Thank you.


The error message that you are reporting is returned when any one of xwave, ywave or srcwave are not appropriate for ImageLineProfile. If you run the code I suggested under the debugger you should be able to check if both xwave and ywave are real numeric waves and that w is a 3D numeric wave.
Thank you all for helpful comments.
I forgot to specify the folder where the src wave is located.
Thanks again.