Speeding Up A Function

Hi All,

I want to speed up the time required to process the following function, which runs through a list of images and creates an ROI boundary for each image that is seed filled. I suspect that the main speed component is associated with the size of the image file (#number of pixels), however maybe something else about the loop is also slowing it down. Any suggestions. Thanks

function makeROIContour(imagename)
    wave imagename
    wave m_roimask
    string XL,YL,xwavelist,ywavelist,M
    variable H,W,Index
    xwavelist=wavelist("*x",";","")
    ywavelist=wavelist("*y",";","")
    H=dimsize(imagename,0)+69
    W=dimsize(imagename,1)+71
    M=num2str(index)
    do
        XL = stringfromlist(index,xwavelist,";")
        YL = stringfromlist(index,ywavelist,";")
        if(strlen(XL) == 0)
            break
        endif
        imageboundarytomask width=h,height=w,xwave=$XL,ywave=$YL,seedX=0,seedy=0
        string xw="xROI"+M
        duplicate/o M_roimask, $XW
        index+=1
        m=num2str(index)
    while(1)
end
How many items are in xwavelist and ywavelist? Large lists (> 1000 items) tend to be slow.
Instead of Duplicate, you can also move M_roimask with Rename.
How long does it take now and what is the target duration?

Btw. your strlen check should also check for YL to be on the safe side.

This is definitly something you can speed up with writing threaded code, but as this is bit more involved, I would put that at the end of the things-to-try-list.

Hi Thomas,

The length of the wavelist is less than 50. And it currently takes 15 seconds to complete the loop, this seems very long.

Also, to be more accurate, the wavelists (x and y) are contour traces from an image, which I want to fill in using the imageboundarytomask and seed fill.

I tried the Rename instead of duplicate...this results (at end of loop) in creating a single wave which is named after the final instance of the $XW at the end of the loop (and no time save).

Cheers,

Clayton

Duplicate is relatively cheap by comparison with ImageBoundaryToMask. I expect the latter to be the place where you spend most processing time. Your loop is ideal candidate for multithreading.

A.G.
WaveMetrics, Inc.
By multithreading, do you mean create a function to do the imageboundarytomask, and another function to do a seed fill, and then call them separately within the main function?

Thanks,

clayton
It depends on the relative size of the filled image. In general, seed-fill algorithms are somewhat tricky to implement and would be slow as user functions. For most applications where h and w are <1k pixels or so, ImageBoundaryToMask is going to be fairly efficient. It is not clear what the ultimate goal of this function. If you are trying to implement filled contours this is probably the slow way to go about it because each ImageBoundaryToMask effectively starts from scratch.

A.G.
This above code is one component of trying to write an object finder for images which contain rectangular objects with varying intensity. See attached image ("objfind"). Here is the logic I've implemented to do the ObjFind

1st - Define a number of z contours for an image.
2nd - Extract the X and Y contour traces to a folder
3rd - Fill each contour by conducting ImageBoundaryToMask and then ImageSeedFill.
4th - Perform ImageAnalyzeParticles on the SeedFill images to define objects at each plane of the contour
5th - Implement some conditional statements to throw away things which are not objects of interest (see attached figure2).

The 3rd step above is very slow and I'm trying to figure out how to speed it up.

ObjFind.jpg (442.69 KB)
ctmckee wrote:
This above code is one component of trying to write an object finder for images which contain rectangular objects with varying intensity. See attached image ("objfind").


I am not a big fan of your approach. It is not clear to me how you define contours. Looking at your sample I noticed that several blobs had more than one contour which is clearly not desirable.

I confess I do not understand much about gel analysis but I am familiar enough with the pictures to note that many of the blobs are not exactly rectangles. Before we go any further, have you considered running simple particle analysis? The idea is that for any threshold level, you may consider each one of your rectangles as a particle whose center of mass can be determined and where the fitting ellipse would give you both the width and length of the blob. In fact, you can use the fitting ellipse to generate a pretty good matching rectangle to synthesize the image from a limited set of parameters.

A.G.
Igor wrote:
ctmckee wrote:
This above code is one component of trying to write an object finder for images which contain rectangular objects with varying intensity. See attached image ("objfind").


I am not a big fan of your approach. It is not clear to me how you define contours. Looking at your sample I noticed that several blobs had more than one contour which is clearly not desirable.

I confess I do not understand much about gel analysis but I am familiar enough with the pictures to note that many of the blobs are not exactly rectangles. Before we go any further, have you considered running simple particle analysis? The idea is that for any threshold level, you may consider each one of your rectangles as a particle whose center of mass can be determined and where the fitting ellipse would give you both the width and length of the blob. In fact, you can use the fitting ellipse to generate a pretty good matching rectangle to synthesize the image from a limited set of parameters.

A.G.



Agreed, having more than one contour is undesirable for a single "blob" object; what you're seeing in that image is all the instances (as a function of defined contours in the z direction) where the object is more rectangular than circular (the final bit of code would need to remove repeat instances of a found object with some argument for when a band is....."full"). In this sense, it's analogous to your to suggestion to run particle analysis and "that for any threshold level, you may consider each one of your rectangles....."

In my case, I was trying to get around the problem that several of the objects are not exactly rectangles (as you noted) and that if you try to analyze the image using a single threshold you find things which are not bands. So, I tried to analyze the image as a function of filled z contour traces, in this case, objects which are non rectangular when viewed for the full z-range, are rectangles (and become more or less rectangular) as they approach their peak intensities. I guess, a loop that runs through every threshold level (0-255) and conducts imageanalyzeparticles will achieve the same goal (using appropriate conditional statements for object removal). I'm assuming based on your response, that this will be faster; however, I will still need to address the issue of removing objects that are found more than once with a bit of logic to determine if the band is "full" at a given threshold. I'll right it up and give it a go.

Thanks

Clayton
ctmckee wrote:
In my case, I was trying to get around the problem that several of the objects are not exactly rectangles (as you noted) and that if you try to analyze the image using a single threshold you find things which are not bands. So, I tried to analyze the image as a function of filled z contour traces, in this case, objects which are non rectangular when viewed for the full z-range, are rectangles (and become more or less rectangular) as they approach their peak intensities. I guess, a loop that runs through every threshold level (0-255) and conducts imageanalyzeparticles will achieve the same goal (using appropriate conditional statements for object removal). I'm assuming based on your response, that this will be faster; however, I will still need to address the issue of removing objects that are found more than once with a bit of logic to determine if the band is "full" at a given threshold.


I'd describe the objects that do not appear rectangular as "smeared". Regardless of the process that gives rise to this image, you can pick some threshold value that yields a particle at a position that is pretty close to the center of the blob. If your goal is to find an exact representation for the blob you could use some approximation (fit to ellipse which I mentioned before) or if the intensity profile is really important to you, I see no reason why you can't extract the original data around the blob into a 2D wave and use curve fitting to obtain an "optimal" rectangle representation. Again, I do not know your application so I'm not sure this extra effort is worthwhile.

I'd also note that in many instances a completely different approach may yield (efficiently) most of the relevant information. If you open the Image Processing Tutorial you will find in section 5 example of locating objects using correlations. In your application I would try to correlate your images with a small rectangle. Execute ImageThreshold on the result and you will obtain correlation spots at the centers of the matching rectangles. The shape of the 2D correlation peaks can be used to analyze the dimensions of the rectangles.

A.G.
WaveMetrics, Inc.