Image Tools
Background
This package is presented as a way for users to load, display, calibrate, manipulate, and print out views from sets of TIFF, jpg, or other image files as well as internally-existing xy/image waves without needing to write code.
Operation
Once installed, the package is accessible from the Analysis --> Image Tools sub-menu.
The displayed content is divided as four frames.
- An image display window shows the currently active image
- A control bar on the top of the main display sets the parameters in the viewing window
- A histogram graph shows the histograms for the image being displayed.
- Operation of the package is done using inputs on a control panel.
Image Control Bar
- Expand window size to free ..., minimum (showing all controls) [..], or preferred [ ]
- Change the color scale used to display the image (main and split)
- Change the image range (contrast adjustments) using sliders or numerical inputs or invert (only for main image)
- Split view to show two images from current folder side-by-side or top-to-bottom (default)
- Swap main and split images
Main Tab
Image Displayed
- Step through images that are loaded as sets using buttons to advance or go backward in the loaded sets.
- See the image size (pixels) and bit depth.
- View/Add notes to an image file (wave).
- Play a movie from a stack
Display Information
- Shows the positions of the marquee when drawn on the image
- Toggle on/off the histogram display with linear and log scales as well as cumulative and derivative histograms.
- Scale the derivative histogram to search for positions of zero crossings (peaks in histogram).
- Choose a region of interest (RoI) for a sub-set of analysis
- Choose inside, outside, inside - outside, and outside - inside analysis for histogram
- See where the RoI is in image coordinates.
- Lock the RoI to continue using the selection tool on the image.
- Shows the min/max in the image and in the selected RoI (if present)
Load Tab
Load Image(s)
- Load a single RGB image, multiple RGB images, a folder of RGB images, or a selection of RGB images from a stack.
- Load uncompressed or compressed TIFFs as well as other image file formats
- Do the same to load grayscale images.
- Load / Convert existing xy waves to a format that can be used within the package
- Choose to keep the source (or not), to extract any one or all of the RGB channels, and/or to create a grayscale image
- Consolidate a set of individual images into a stack
- Create your own image file loader and have it automatically recognized (ask for details)
Calibrate Tab
Calibrate XY
- Set a calibration factor for pixel, image width, or image height to apply locally or globally
Calibrate Intensity
- Invert, remove negatives, remove outliers, normalize (by height or flux density), and apply an equation using "I" for intensity as well as "x,y" for position
Example Equations: (I^2) will square the intensity or (I < 20 ? 0 : I) will set all intensity values below 20 to zero
Process Tab
Remove Background
- Manually set or edit grid points that denote the background locations
- Create NxM grids that ignore marquee regions (rectangle or oval), threshold, or fill regions
- Apply an operation to remove a background having various plane orders through the grid points
- Remove a zero order plane to subtract the minimum value from the image
Threshold
- Apply a thresholding method to one image, each image, or all images in a stack
- Select various threshold methods as documented in the Igor Pro options, including manual or range
- Fill the threshold
Mask Image Regions
- Use drawing regions, the marquee, a threshold image, a fill image, or a split image highlight regions of interest
Stack Math (for Image Stacks)
- Average + Standard Uncertainty, Derivative, or Integral over the stack
Split Math (when view is split)
- Add, Subtract, Multiply, Divide with left (operation) right. Process only displayed or process selectively for stacks.
- Input equation using L (left) and R (right) for split math operation.
Split Logic (when view is split and when both views are threshold or fill images)
- AND, OR, XOR, NOT, NOR operations for L (OP) R processing
Crop to Marquee
- Crop using the marquee to exact or to smallest feature
Publish Tab
Image
- Turn on/off axes
- Turn on/off scale bar, set its location / color, and set its line+bar thickness values
- Add color bar calibrator
Layout
- Store the image to a list to use for a layout (with tags as desired) or a contact print format
- Allow the layout image to update dynamically as changes are made to the main image
Caveats
- This package has been developed to work with single-channel images. It may do some things correctly with RGB images or 4-stack images, however no guarantees are given for these types of images. Convert RGB or 4-stack images to grayscale or read only each individual channel accordingly.
- This program can load image stacks (TIFF movies). That does not however mean that it will handle them all with equal efficiency. Load larger files as stacks using the selections to load only a certain range in the movie and/or to load only a certain sequence (e.g. every 10th image).
Further Help
A few selected tutorial videos for portions of this package are available at either link below.
Project Details
Current Project Release
Release File: | Image Tools v4.10.zip (200.85 KB) |
Version: | 4.10 |
Version Date: | |
Version Major: | 4 |
Version Patch Level: | 10 |
OS Compatibility: | Windows Mac-Intel |
Release Notes: |
Squashed Bugs ● properly ignores fill or threshold waves in creating histograms Improved Code ● streamlined options in function calls, especially from window hook functions Improved UI ● calibration line on image displays in increments 1, 2, 5, and 10 New Features ● LOAD: consolidate existing individual images into a stack
|
Forum
Support
Gallery
Igor Pro 9
Learn More
Igor XOP Toolkit
Learn More
Igor NIDAQ Tools MX
Learn More
I would be grateful to hear from folks who find this package useful, who would like to see features added to it, or who would like to contribute to its development. Please contact me with comments here or via a direct email.
January 14, 2020 at 11:23 am - Permalink
JJ, while I don't use your tool (yet) I took a look how things are done in your code. ;) I found a few bugs and inconsistencies, so I thought you might want to know about them. Here is a (non-exhaustive) list of what I found so far:
1) the include statements fail if not all the procedures are inside the standard procedures folder. I often rather want to have just a shortcut to the main procedure (Image Tools Main.ipf in this case) and leave all the rest somewhere else. This would work if you would provide relative paths to the included files, e.g.,
and so on.
2) I am not such a fan of creating stuff upon start of every experiment. Why do you want to initialize the package upon start? It might be better to initialize the folder structure upon first start.
3) line 384 in Image Tools Main.ipf: Missing /Z flag in
wave swave = $lwfile
4) The controls overlap and have an inconsistent font size on Windows (see attachment).
5) Toggling marquee 'lock' on and off shifts the marquee area down a bit each time.
6) If I click the |< button directly after start, the 'Folder' popup menu appears, which is broken at this stage.
7) I think do_strsplitmath() has a possible bug: If the name of limg contains an 'r' the command execution would break, since all 'r's are replaced by the name of rimg.
8) If I switch loading to Internal Data Folder, press Convert but then cancel I get an error.
9) Related to 8, I then can click through the different tabs without a proper wave loaded, which breaks all kinds of things. The tab controls need hard checks if / when they are safe to be activated.
July 25, 2023 at 08:24 am - Permalink
@chozo -- Thanks. I agree, parts of the code may need a robust sanity check. A few quick notes ...
1) I prefer to "hide" supporting procedures in a folder within the main folder. I'd not considered this would cause disruption using your approach. I'll implement the relative file path designation to allow it.
2) I should only be checking behind at the start of each experiment to discover whether the Image Tools procedures have been updated. I'll make sure this is the case.
4) Ah yes, Windows. I'll have to fire up my Parallels version and adjust.
5) I've fought with the distinctions in placement of a marquee as pixels versus axes versus graph coordinates until my head spins. I'll revisit this.
3, 6-9) I should hope to tackle these issues ASAP.
I think you've given me my plans for the upcoming week, and I'm looking forward to the non-non-exhaustive list. :-)
July 25, 2023 at 10:10 am - Permalink
@chozo -- v3.32 should fix all but 4) and 5)
July 25, 2023 at 05:18 pm - Permalink
Great, here's more. :)
1) The #include issue was not fully resolved yet. You need to put a ':' in front of each statement in Image Tools Process.ipf.
2) ImageLoad is apparently unable to load compressed Tiff images (at least with LZW), so you need to add a /Z flag and handle the loading error (lines 464 ... in Load Tools).
3) The Histogram graph is actually partly outside my monitor area. You might want to calculate the size of the image display and the placement of the histogram view according to the screen size. (This one is a bit tedious, so just if you want to go for it.)
4) Similar to 3, enabling split view can possibly stretch the whole thing far beyond the available screen area.
5) I was trying to load a tiff image now, but the Folder popup and <> buttons never appeared and the loaded image was also not displayed automatically. So I was unable to display the loaded image.
6) I guess it is not intended to save the main graph, so I would use /K=1 when building the graphs for the tool to prevent the dialog.
7) When I lock the marquee and drag a new marquee anyway, all values change to NaN (this may be intended)?
8) When I press 'include' for Contact print without selecting anything in particular, I get an error in line 198 in Publish.ipf
9) When I remove the pre-placed cursor from the histogram, I get an error. Handle that the cursor might be absent or make sure that it always exists (by forcefully readding it). (Also, why is it called B when it is cursor A, or does the B stand for something else?)
10) imgT_bckg... waves are created in the current folder and not in packages (this may be intended?).
11) In split view (using one of the background-subtracted waves), the BW, invert and color controls do not seem to work properly, as they apply to both, just the left or just the right image depending on whether they are toggled on or off.
12) Related to 11, after toggling the BW checkbox and removing the split, I managed to have the wrong image displayed so that the contrast sliders give errors.
13) I just realized you still have the aftercompiledhook() in there, which still creates all data each time a new Igor session is started. Of course, your choice if you want to keep it that way. :)
14) Just curious, your default image gives a highly noisy impression with the rapidly varying sin/cos. I wondered if something less frequent like img_default = 200*sin(x/30)*cos(y/30)+200 would be nice.
That's all for now. I can give it some more testing when the image loading + display works.
July 25, 2023 at 08:29 pm - Permalink
In reply to Great, here's more. :) 1)… by chozo
Quick comment about Chozo (2) above:
ImageLoad supports reading TIFF images in two branches: Igor's TIFF code and LibTiff. Igor's TIFF code does not support LZW compression. If you are working with compressed TIFF it is best to use /BIGT=1. If that fails to read the image use /RAT to get more information about the file to determine how to proceed.
A.G.
July 26, 2023 at 08:11 am - Permalink
@chozo -- I'll handle the critical errors promptly. Otherwise ...
2) I'll revise with the /Z and decide what is best to proceed. In the meantime, I suggest loading the compressed tiff in a standard way and using convert folder to add the compressed tiff.
3) and 4) I will eventually prefer to handle this by including a #if compiler reference to check whether the Screen Sizer package is installed in the experiment ( https://www.wavemetrics.com/project/ScreenSizer ). It has functions to position windows by fraction of screen size. I'm reluctant rebuild the features in the Screen Sizer toolset again from scratch, especially since I think (pat myself on the back here) that the Screen Sizer package does what is needed in a robust, easy, and intuitive way. In the meantime, 27in+ 4K+ monitors (or MacBook Pro 16in Retina monitors) are great assets to have when you must work with images. :-)
13) The AfterCompiledHook is there to assure that Image Tools handles updates itself properly. The package folder is created from scratch only the first time. After this, the code drops into the imgT_Update() function. This checks the version number of the current against the version number when the experiment was first created. If the version number changed, the package updates itself. I've only had one time that I truly needed to add additional data to the package (perhaps back at the version 1 or 2 stage). I see that I could simply reference back to when this happened and/or check so as not recreate the scaling factors (e.g. if they exist). Otherwise, I still have to drop to an update branch after compiling because sometimes the panel controls change. So I have to also the package to remove and recreate the image + panel. I am curious whether you have an alternative way to resolve the need to handle package updates that do not use a hook function.
July 26, 2023 at 09:20 am - Permalink
3) / 4) It is actually not as tedious as I made it seem. :) Here is some code as a start:
if (cmpstr(IgorInfo(2),"Macintosh")==0) // Mac
string TFTInfo = StringByKey("RECT",ReplaceString(",RECT",StringByKey("SCREEN1",IgorInfo(0),":"),";RECT"),"=")
TFTResX = (Str2Num(StringFromList(2,TFTInfo,",")) - Str2Num(StringFromList(0,TFTInfo,",")))*(72/ScreenResolution)
TFTResY = (Str2Num(StringFromList(3,TFTInfo,",")) - Str2Num(StringFromList(1,TFTInfo,",")))*(72/ScreenResolution)
else // Windows
GetWindow kwFrameInner wsizeDC
TFTResX = (v_right-v_left)
TFTResY = (v_bottom-v_top)
endif
variable WinTop = 50, WinLeft = 250 // screen margins
variable WinBottom = TFTResY - 250
variable WinRight = TFTResX - 350
WinBottom = limit(WinBottom, WinTop+300, inf) // min size
WinRight = limit(WinRight, WinLeft+300, inf)
NewImage/K=1/N=$k_imgDisplay itd
MoveWindow/W=$k_imgDisplay WinLeft*pix, WinTop*pix, WinRight*pix, WinBottom*pix
Also, you then might want to use within disp_ShowHistograms():
AutoPositionWindow/E/M=1/R=$k_imgDisplay $k_histGraphs
13) I assume you are operating from the POV that the tool will be used when it is (manually) loaded by the user. But I usually have all tools I might use loaded all the time, so some procedures creating data all the time is somewhat undesired. There are many ways to approach that. To roll with your current implementation, how about only running the update function within AfterCompiledHook()? If the updater does not find any folders, this means the tool has not been started => back out quietly without doing anything. This way you never have to do any initialization from this function, which can be solely shifted to the startup of the tool. I personally have update code attached to the window hook functions, however. In general, I also make sure that the code works with all previous graphs/panels ever created in the past which were left open (yes, this can be tiresome at time, I know, but I also did not discover the magic trick to teach my users to properly close tools when they are done).
July 26, 2023 at 01:14 pm - Permalink
@chozo - Try v3.40, especially to load compressed TIFFs. A few notes in the meantime ...
1), 5) - 7), 9) fixed
2) try it and let me know (I have no immediate access to compressed TIFFs)
3) and 4) to be addressed later when I have enough motivation to include compiler directives to test for ScreenSizer
8) I suspect this was an issue with something else and this error should not happen again
10) yes, I keep the background waves in the source folder in case someone wants to export just that folder and post-process separately
11) the color scale goes across both but the scalings and invert only work on the main window. This is purposeful to allow comparisons such as .... Is my background corrected image really better than simply adjusting the lower and upper contrast on the main image?
12) the B&W checkbox is removed (perhaps forever or at least until I decide what purpose it really should serve and how to handle it more robustly)
13) see my previous note
14) cool and now implemented!!!!
Follow up -- You were posting when I was.
* I'll look at incorporating your code for window sizings.
* I missed the AutoPosition ... function.
* OK. Now I understand exactly what you mean. I should initialize the package at the menu call, not at compilation. Apologies ... I see the difference once you explained how you operate. I prefer to load procedures only as needed. As to assuring backward compatibility with previous panel controls ... not my cup of tea. I'd rather just kill off an "outdated" panel and redraw the new panel.
Please let me know whether you can load compressed TIFFs. I can implement further changes and any bug fixes as needed for a 3.41 version.
July 26, 2023 at 01:24 pm - Permalink
JJ - No, unfortunately compressed images do not load yet. I'll attach a few example files for you to play around with. I think moving to compressed tif would be very beneficial, since the file size can be 1-2 orders of magnitude smaller. To batch compress images you could for example use ImageMagick.
July 26, 2023 at 07:53 pm - Permalink
@chozo -- I was able to load both images, albeit not properly into a single channel grayscale. I could extract the R, G, or B channels.
Let's go off-line. Follow up with me at weimerj at uah dot edu.
July 27, 2023 at 06:50 am - Permalink