If you just want to estimate the spot area, that is even easier than fitting a
Gaussian to the shape. You can do something like:
# Convert to floating point; rearrange to 3 x width x height; collapse
to width x height
$bw_image = $pdl1->float->mv(2,0)->sumover
# Generate mask image
$mask = ($bw_image < 255*3/2);
If you’re actually trying to integrate photometry of your chromatographic
images, you need to think about what, exactly, the dye is doing to the paper.
The brightness of a dyed spot is multiplicative with more dye — each unit
concentration of dye on the paper reduces the reflectivity at a particular
wavelength by the same factor, so you don’t want to be integrating brightness
or even darkness — you want to be integrating
-log(brightness/undyed-brightness). The logarithm operation will screw you up
unless you have a bright reference (fortunately you do — the undyed paper) and
a dark reference (I don’t see one there). You’ll still have issues with that,
because the exponential decay is at each wavelength, and the spots change color
as they get darker - so the overall absorptivity per unit dye shifts as the
spot gets darker. These aren’t PDL issues, they’re chromatographic issues.
Anyhow, you might be better off just working with the geometry, unless you just
need qualitative analysis. To find the area of a spot, in pixels, you can sum
a region of the $mask.
Separating the spots on a single image is something you can do by explicit
slicing, or you can try to get fancy. Here’s one way to get fancy, by using a
convolution to estimate the total number of masked points within a given
radius. It’s very wasteful of CPU cycles, but quick to code up — which fits
within the philosophy of PDL.
# Make an image that is 1 within $rmax of the center of the image, 0
elsewhere.
# Choose $rmax large enough to include a spot; small enough to exclude
neighbors.
$rmax = 50;
$mask_kernel = (rvals( $rmax * 2 + 1, $rmax * 2 + 1) <= $rmask;
# Create an image containing just how many mask=true points are within
# rmax of each pixel. This is wasteful because you only need like 8
points,
# but calculate the sum for each pixel in the whole image.
$mask_smooth = $mask->convolveND($mask_kernel);
# Now identify the middle of each spot. Smooth the mask_smooth even
further,
# to create a local maximum at the center of each spot. Then use
range() to
# generate a 3x3 collection of image lags (total dims 3 x 3 x w x h)
shifted
# in each of the 9 possible directions, and zero out the unshifted one
in the middle.
# Local maxima are places where the original smsm image is larger than
any of
# its shifted copies.
$mask_smsm = $mask_smooth->float->convolveND($mask_kernel);
$mask_smsm_lags = $mask_smsm->range( ndcoords(3,3)-1,
$mask_smsm->shape, ’e’);
$mask_smsm_lags->((1),(1)) .= 0;
$localmax_mask = ($mask_smsm > $mask_smsm_lags->maximum->maximum);
# $localmaxima is 2xN — it’s the pixel coordinates of all the local
maxima in mask_smsm,
# which should be the center of each spot. The area of each spot is
just the smoothed mask
# value at that location.
$localmaxima = whichND($localmax_mask);
$areas = $mask_smooth->indexND($localmaxima);
print “Spot areas found:\n”;
for $i($localmaxima->dog){
print $localmaxima->( :, ($i) ),
“: area is “.$areas->(($i)),
“\n”;
}
> On Apr 23, 2015, at 8:24 AM, Demian Riccardi <[email protected]> wrote:
>
>
> Thanks, Craig.
>
> Ideally, I would like to automatically fit a two gaussian to each blob, and
> integrate it to get the total relative contents of the blobs, which I could
> then connect back with the known amount of standards added. For starters I
> was able to read in the file using PDL::IO::Image (awesome) and rimage. I
> tried using PDL::IO::Pic rim, but that spit out an error for some reason.
>
> I sliced each column of the image and printed out the minimum value of the
> image unit (RGB value? sorry, I’m not an expert in manipulating images!).
> This spit out something that looked somewhat reasonable when graphed. Thus,
> I should be able to grab out the index of the minimum paired with a column to
> fit a the gaussian, but it there an easier way to do this?
>
> I’m still a PDL newbie, so even slicing is not trivial for me at this point…
> bah!
>
> Demian
>
> below is a copy paste from an IPerl Notebook (I hope it translates!).
>
>
> In [31]:
>
> use Modern::Perl;
> use PDL;
> use PDL::IO::Image;
> In [32]:
>
> my $pdl1 = rimage('Desktop/TLC_arg.jpg');
> print $pdl1->info;
> Out[32]:
> PDL: Byte D [2625,116,3]
> 1
> In [37]:
>
> foreach my $ic (0 .. 2624){
> my $col = min($pdl1->slice("$ic"));
> print $col . "\n";
> }
>
>
>> On Apr 23, 2015, at 9:34 AM, Craig DeForest <[email protected]
>> <mailto:[email protected]>> wrote:
>>
>> How do you want to quantify them? E.g. are you doing photometry or are you
>> doing geometry? PDL can help you either way. The “rim” function will load
>> a color image (say a PNG or JPG) into a structured array. After that you
>> can manipulate it. Simple geometric extraction or brightness extraction are
>> easy after that.
>>
>>
>>
>>> On Apr 22, 2015, at 2:14 PM, Demian Riccardi <[email protected]
>>> <mailto:[email protected]>> wrote:
>>>
>>> Hello,
>>>
>>> A need has come up for analyzing some thin layer chromatography in one of
>>> my chemistry labs (see the attached jpg; I know it isn’t perfect). Is there
>>> a way I can pull in this image and automatically quantify the spots? Two
>>> of the sets of four are standards and the other two are samples.
>>>
>>> I was able to load it in with PDL::IO::Image so I know there must be a way!
>>>
>>> Demian
>>>
>>> <TLC_arg.jpg>
>>> ------------------------------------------------------------------------------
>>> BPM Camp - Free Virtual Workshop May 6th at 10am PDT/1PM EDT
>>> Develop your own process in accordance with the BPMN 2 standard
>>> Learn Process modeling best practices with Bonita BPM through live exercises
>>> http://www.bonitasoft.com/be-part-of-it/events/bpm-camp-virtual-
>>> <http://www.bonitasoft.com/be-part-of-it/events/bpm-camp-virtual->
>>> event?utm_
>>> source=Sourceforge_BPM_Camp_5_6_15&utm_medium=email&utm_campaign=VA_SF_______________________________________________
>>> pdl-general mailing list
>>> [email protected] <mailto:[email protected]>
>>> https://lists.sourceforge.net/lists/listinfo/pdl-general
>>
>
------------------------------------------------------------------------------
BPM Camp - Free Virtual Workshop May 6th at 10am PDT/1PM EDT
Develop your own process in accordance with the BPMN 2 standard
Learn Process modeling best practices with Bonita BPM through live exercises
http://www.bonitasoft.com/be-part-of-it/events/bpm-camp-virtual- event?utm_
source=Sourceforge_BPM_Camp_5_6_15&utm_medium=email&utm_campaign=VA_SF
_______________________________________________
pdl-general mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/pdl-general