<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom"><title>Cris’ Image Analysis Blog - criticism</title><link href="https://www.crisluengo.net/" rel="alternate"></link><link href="https://www.crisluengo.net/feeds/criticism.atom.xml" rel="self"></link><id>https://www.crisluengo.net/</id><updated>2015-06-03T22:51:00-06:00</updated><subtitle>theory, methods, algorithms, applications</subtitle><entry><title>The curse of the big table</title><link href="https://www.crisluengo.net/archives/730" rel="alternate"></link><published>2015-06-03T22:51:00-06:00</published><updated>2015-06-03T22:51:00-06:00</updated><author><name>Cris Luengo</name></author><id>tag:www.crisluengo.net,2015-06-03:/archives/730</id><summary type="html">&lt;p&gt;As an Area Editor for Pattern Recognition Letters, I&amp;rsquo;m frequently confronted with papers containing big tables of
results. It is often the deblurring and denoising papers that (obviously
&lt;a href="/archives/490" title="Evaluating noise filters"&gt;using PSNR as a quality metric&lt;/a&gt;!) display lots of large tables
comparing the proposed method with the state of the art …&lt;/p&gt;</summary><content type="html">&lt;p&gt;As an Area Editor for Pattern Recognition Letters, I&amp;rsquo;m frequently confronted with papers containing big tables of
results. It is often the deblurring and denoising papers that (obviously
&lt;a href="/archives/490" title="Evaluating noise filters"&gt;using PSNR as a quality metric&lt;/a&gt;!) display lots of large tables
comparing the proposed method with the state of the art on a set of images. I&amp;rsquo;m seriously tired of this. Now I&amp;rsquo;ve set my
foot down, and asked an author to remove the table and provide a plot instead. In this post I will show what is wrong
with the tables and propose a good alternative.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m just taking a &lt;a href="http://dx.doi.org/10.1109/TIP.2012.2235847"&gt;random denoising/deblurring paper&lt;/a&gt; as example. It has
four tables like this one:&lt;/p&gt;
&lt;p class="centering"&gt;&lt;img alt="A big table." src="/images/PSNR_big_table.png"&gt;&lt;/p&gt;
&lt;p&gt;The main problem with this table is that it doesn&amp;rsquo;t allow comparison of the various methods without looking at each
column individually, study the numbers in it, and determine the magnitude of the difference between the largest value
and all other values. Very helpfully, the largest value has been bolded. But it is still not a trivial task to determine
how significant the advantage of one method over the other is. To further complicate things, PSNR and FSIM values have
been mixed in the same column (presumably to save space), meaning that you need to compare odd rows and even rows
separately.&lt;/p&gt;
&lt;p&gt;In short, the raw dumping of numerical results helps no-one, except maybe the authors, who are able to hide the
insignificance of the improvement of their proposed method. The purpose of a scientific paper is to communicate research
results, not to let the reader repeat all your calculations. Raw data has no place in a scientific paper (of course
there are always exceptions), the author should strive towards explaining his/her findings as simply and compactly as
possible. In the same way that long, flowery prose is to be avoided, so are long, flowery displays of data.&lt;/p&gt;
&lt;p&gt;For example, how many readers are interested in seeing the value of the PSNR obtained when applying the new algorithm to
the image &amp;lsquo;Boats&amp;rsquo;? Very, very few is my guess. It might be nice to provide the raw results as supplementary data, so
that other people can use those values in their own comparisons (but better, of course, is to provide the code so others
can replicate the experiments). The majority of the readers will want to compare the results of the new algorithm to the
previous state-of-the-art. Why not help them do this?&lt;/p&gt;
&lt;p&gt;I would propose to display these results using a box plot:&lt;/p&gt;
&lt;p class="centering"&gt;&lt;img alt="A box plot." src="/images/PSNR_big_table_graph.png"&gt;&lt;/p&gt;
&lt;p&gt;In this plot we can directly compare the various methods against each other. I have separated the two metrics into
separate plots, and the whole display still occupies less space than the one table. If strapped for space, it would be
possible to remove two of the x-axes and two of the y-axes, and bring the four boxes close together.&lt;/p&gt;
&lt;p&gt;One problem with this plot is that the distribution displayed by the boxes (especially in the case of PSNR) is driven by
the images themselves, more than by the method. Thus, overlap between these boxes has no meaning other than saying that
PSNR is a poor metric for evaluating this type of method. An alternative solution is to plot the improvement of the
method over each of the state-of-the-art methods:&lt;/p&gt;
&lt;p class="centering"&gt;&lt;img alt="A box plot." src="/images/PSNR_big_table_graph2.png"&gt;&lt;/p&gt;
&lt;p&gt;I have simply plotted the difference between the results for the new method and each of the other methods. PSNR is a
logarithmic measure, so this makes sense, but for the other measure it might make more sense to plot ratios. In any
case, it is now clear that the method improves in most cases, but not in all, and it is easy to see which cases these are.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Edit&lt;/p&gt;
&lt;p&gt;I did not discuss here the other issues with this type of analysis: PSNR values depend very heavily on image
content and should not be used for comparison across images. Are 10 images representative? Why not use all images
in, for example, the
&lt;a href="http://www.eecs.berkeley.edu/Research/Projects/CS/vision/grouping/resources.html"&gt;Berkeley Segmentation Data Set&lt;/a&gt;,
a collection of 500 natural images? Why are there not many different levels of blur compared? With how much blur
does the method finally break down? Etc. Etc.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Edit 2&lt;/p&gt;
&lt;p&gt;If you are curious about how I made these plots, you can
&lt;a href="/code/PSNR_big_table.m"&gt;find the script here&lt;/a&gt;. The &lt;code&gt;boxplot&lt;/code&gt; command is one I wrote myself,
&lt;a href="http://www.mathworks.com/matlabcentral/fileexchange/51134-boxplot"&gt;find it on the MATLAB File Exchange&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;</content><category term="criticism"></category><category term="graph"></category><category term="PSNR"></category><category term="scientific data presentation"></category><category term="scientific paper"></category><category term="table"></category></entry><entry><title>No, that's not a Gaussian filter</title><link href="https://www.crisluengo.net/archives/695" rel="alternate"></link><published>2015-02-06T13:08:00-07:00</published><updated>2015-02-06T13:08:00-07:00</updated><author><name>Cris Luengo</name></author><id>tag:www.crisluengo.net,2015-02-06:/archives/695</id><summary type="html">&lt;p&gt;I recently got a question from a reader regarding Gaussian filtering, in which he says:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I have seen some codes use 3x3 Gaussian kernel like  &lt;/p&gt;
&lt;p&gt;&lt;code&gt;h1 = [1, 2, 1]/4&lt;/code&gt;  &lt;/p&gt;
&lt;p&gt;to do the separate filtering.  &lt;/p&gt;
&lt;p&gt;The paper by Burt and Adelson (The Laplacian Pyramid as a Compact Image Code, IEEE …&lt;/p&gt;&lt;/blockquote&gt;</summary><content type="html">&lt;p&gt;I recently got a question from a reader regarding Gaussian filtering, in which he says:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I have seen some codes use 3x3 Gaussian kernel like  &lt;/p&gt;
&lt;p&gt;&lt;code&gt;h1 = [1, 2, 1]/4&lt;/code&gt;  &lt;/p&gt;
&lt;p&gt;to do the separate filtering.  &lt;/p&gt;
&lt;p&gt;The paper by Burt and Adelson (The Laplacian Pyramid as a Compact Image Code, IEEE Transactions on Communication,
31:532-540, 1983) seems to use 5x5 Gaussian kernel like  &lt;/p&gt;
&lt;p&gt;&lt;code&gt;h1 = [1/4 - a/2, 1/4, a, 1/4, 1/4-a/2]&lt;/code&gt;,  &lt;/p&gt;
&lt;p&gt;and &lt;code&gt;a&lt;/code&gt; is between 0.3-0.6. A typical value of &lt;code&gt;a&lt;/code&gt; may be 0.375, thus the Gaussian kernel is:  &lt;/p&gt;
&lt;p&gt;&lt;code&gt;h1 = [0.0625, 0.25, 0.375, 0.25, 0.0625]&lt;/code&gt;  &lt;/p&gt;
&lt;p&gt;or  &lt;/p&gt;
&lt;p&gt;&lt;code&gt;h1 = [1, 4, 6, 4, 1]/16&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I have written previously about &lt;a href="/archives/22" title="Gaussian filtering"&gt;Gaussian&lt;/a&gt;
&lt;a href="/archives/150" title="Gaussian filtering with the Image Processing Toolbox"&gt;filtering&lt;/a&gt;,
but neither of those posts make it clear what a Gaussian filter kernel looks like.&lt;/p&gt;
&lt;h2&gt;Window size&lt;/h2&gt;
&lt;p&gt;In a &lt;a href="/archives/150" title="Gaussian filtering with the Image Processing Toolbox"&gt;previous post&lt;/a&gt; I discussed how the size in
pixels of the kernel is given by the chosen σ. Clearly, the Gaussian bell curve has a size given by the σ, and we need a
sampling window large enough to contain the whole bell. With the convolution operation, we assume zero values outside
the window. The Gaussian has long tails (in fact, it never reaches zero!), but it reaches values close to zero quite
quickly. For example, at 3σ the Gaussian has a value of 0.0044, and if we assume it to be equal to zero after that, we
ignore less than 0.3% of the total &amp;ldquo;weight&amp;rdquo; of the curve. Using a larger window to sample the same Gaussian therefore
will not increase the precision by much, but using a smaller window quickly degrades the sampled Gaussian so that it
doesn&amp;rsquo;t look like a Gaussian any more. This is why I always recommend to cut off at 3σ, though in some circumstances it
might be better to increase that value. This is a graphical representation of the Gaussian cut off at various values of
σ:&lt;/p&gt;
&lt;p class="centering"&gt;&lt;img alt="Gaussian cut off at various values of sigma" src="/images/gaussian_filtering_1.svg"&gt;&lt;/p&gt;
&lt;p&gt;Note that the shape in the first two plots is very different to that of a Gaussian bell curve. It is the slow
convergence to zero at the tails that give the Gaussian its desirable properties. I mention this here because it is not
uncommon to find improperly implemented Gaussians.
Because &lt;a href="http://www.mathworks.com/products/image/"&gt;MATLAB&amp;rsquo;s Image Processing Toolbox&lt;/a&gt; implements the Gaussian
with &lt;a href="/archives/150" title="Gaussian filtering with the Image Processing Toolbox"&gt;two parameters instead of one&lt;/a&gt; (i.e. the
kernel size and the σ), users get confused and fill in incompatible values. This week I ran
into &lt;a href="http://dx.doi.org/10.1364/BOE.3.001127"&gt;a paper&lt;/a&gt; that applied&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;an 11x11 pixel Gaussian filter with standard deviation σ=25 pixels.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Yes, the authors in this paper used MATLAB to implement their algorithm. I have plotted such a filtering kernel (the
one-dimensional version of it):&lt;/p&gt;
&lt;p class="centering"&gt;&lt;img alt="Gaussian cut off so early it looks like a box filter" src="/images/gaussian_filtering_2.svg"&gt;&lt;/p&gt;
&lt;p&gt;Does this look like a Gaussian to you? This was not in some obscure paper by some obscure scientists in some obscure
university in some obscure country. This came from Duke University,
&lt;a href="http://www.timeshighereducation.co.uk/world-university-rankings/2014-15/world-ranking/institution/duke-university"&gt;ranked number 18 in the Times Higher Education&amp;rsquo;s World University Ranking&lt;/a&gt;.
I mention this to reinforce how common these problems are.&lt;/p&gt;
&lt;h2&gt;Integer approximations&lt;/h2&gt;
&lt;p&gt;Next, let&amp;rsquo;s look at the &lt;code&gt;[1, 2, 1]/4&lt;/code&gt; kernel that is sometimes referred to as a Gaussian kernel. Remember that outside
of this 3-pixel window, the kernel has a value of 0. This is thus equivalent to &lt;code&gt;[0, 1, 2, 1, 0]/4&lt;/code&gt;, a clearly
triangular shape. A kernel with triangular weights is the convolution of a uniform kernel with itself. You
can &lt;a href="/archives/22" title="Gaussian filtering"&gt;read all about the problems introduced by the uniform kernel&lt;/a&gt;. The triangular
kernel fixes some of those, but still is not nearly as good at suppressing high frequencies as the Gaussian kernel. If
you convolve the uniform kernel with itself many times, you approximate the Gaussian kernel. Thus, a triangular kernel
is a very rough approximation to the Gaussian kernel. Here is a plot of a continuous-domain triangular kernel and
samples corresponding to the &lt;code&gt;[1, 2, 1]/4&lt;/code&gt; kernel:&lt;/p&gt;
&lt;p class="centering"&gt;&lt;img alt="Triangle filter" src="/images/gaussian_filtering_3.svg"&gt;&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;[1, 4, 6, 4, 1]/16&lt;/code&gt; kernel that the reader mentioned above asked about is a different approximation
to the Gaussian, using only small integer values. I plotted it here (black x), together with a Gaussian bell curve (σ=1)
and a sampled Gaussian (circles):&lt;/p&gt;
&lt;p class="centering"&gt;&lt;img alt="Integer Gaussian approximation with actual Gaussian overlaid" src="/images/gaussian_filtering_4.svg"&gt;&lt;/p&gt;
&lt;p&gt;Back in the day, integer computations were much faster than floating-point operations, and thus there was a value in
using this type of approximation. Nowadays, this might still hold in some hardware, but is certainly no longer true in
PCs, GPUs or even smartphones. I recommend that you sample a true Gaussian and stick to floating-point–valued kernels.&lt;/p&gt;</content><category term="criticism"></category><category term="approximation"></category><category term="bad science"></category><category term="filtering"></category><category term="Gaussian"></category></entry><entry><title>Proper counting</title><link href="https://www.crisluengo.net/archives/666" rel="alternate"></link><published>2014-09-23T11:12:00-06:00</published><updated>2014-09-23T11:12:00-06:00</updated><author><name>Cris Luengo</name></author><id>tag:www.crisluengo.net,2014-09-23:/archives/666</id><summary type="html">&lt;p&gt;I just came across an editorial in the Journal of the American Society of Nephrology
(&lt;a href="http://jasn.asnjournals.org/content/10/5/1124.full.pdf"&gt;Kirsten M. Madsen, Am Soc Nephrol 10(5):1124-1125, 1999&lt;/a&gt;),
which states:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A considerable number of manuscripts submitted to the Journal include quantitative morphologic data based on counts
and measurements of profiles observed in tissue …&lt;/p&gt;&lt;/blockquote&gt;</summary><content type="html">&lt;p&gt;I just came across an editorial in the Journal of the American Society of Nephrology
(&lt;a href="http://jasn.asnjournals.org/content/10/5/1124.full.pdf"&gt;Kirsten M. Madsen, Am Soc Nephrol 10(5):1124-1125, 1999&lt;/a&gt;),
which states:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A considerable number of manuscripts submitted to the Journal include quantitative morphologic data based on counts
and measurements of profiles observed in tissue sections or projected images. Quite often these so-called
morphometric analyses are based on assumptions and approximations that cannot be verified and therefore
may be incorrect. Moreover, many manuscripts have insufficient descriptions of the sampling procedures and
statistical analyses in the Methods section, or it is apparent that inappropriate (biased) sampling techniques
were used. Because of the availability today of many new and some old stereologic methods and tools that are
not based on undeterminable assumptions about size, shape, or orientation of structures, the Editors of the
Journal believe that it is time to dispense with the old, often biased, model-based stereology and change the
way we count and measure.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;It then goes on to say that the journal would require appropriate stereological methods be employed for quantitative
morphologic studies. I have never read a paper in this journal, but certainly hope that they managed to hold on to this
standard during the 15 years since this editorial was written. Plenty of journals have not come this far yet.&lt;/p&gt;</content><category term="criticism"></category><category term="assumption"></category><category term="bad science"></category><category term="bias"></category><category term="measure"></category><category term="stereology"></category></entry><entry><title>Automated image-based diagnosis</title><link href="https://www.crisluengo.net/archives/594" rel="alternate"></link><published>2013-08-24T12:52:00-06:00</published><updated>2013-08-24T12:52:00-06:00</updated><author><name>Cris Luengo</name></author><id>tag:www.crisluengo.net,2013-08-24:/archives/594</id><summary type="html">&lt;p&gt;Nowhere is it as difficult to get a fully automatic image analysis system accepted and used in practice as in the
clinic. Not only are physicians sceptical of technology that makes them irrelevant, but an automated system has to
produce a &lt;em&gt;perfect&lt;/em&gt; result, a correct diagnosis for 100% of the …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Nowhere is it as difficult to get a fully automatic image analysis system accepted and used in practice as in the
clinic. Not only are physicians sceptical of technology that makes them irrelevant, but an automated system has to
produce a &lt;em&gt;perfect&lt;/em&gt; result, a correct diagnosis for 100% of the cases, to be trusted without supervision. And of course
this is impossible to achieve. In fact, even if the system has a better record than an average (or a good) physician, it
is unlikely that it is the same cases where the system and the physician are wrong. Therefore, the combination of
machine + physician is better than the machine, and thus the machine should not be used without the physician.&lt;/p&gt;
&lt;p&gt;What often happens then is that the system is tuned to yield a near 100% &lt;em&gt;sensitivity&lt;/em&gt; (to miss only very few positives),
and thus has a very low &lt;em&gt;specificity&lt;/em&gt; (that is, it marks a lot of negative tests as positive). The system is heavily
biased to the positives. The samples marked by the system as negative are almost surely negative, whereas the samples
marked as positive (or, rather, &lt;em&gt;suspect&lt;/em&gt;) are reviewed by the physician. This is supposed to lighten the workload of
the physician. This seems nice and useful, no? What is the problem?&lt;/p&gt;
&lt;p&gt;One example where automated systems are routinely used in the clinic (at least in the rich, western world) is for
screening for cervical cancer. This is done with the so-called &lt;a href="http://en.wikipedia.org/wiki/Pap_test"&gt;Pap smear&lt;/a&gt; since
the 1940&amp;rsquo;s. It takes about 10 minutes to manually examine one smear, which is made on a microscope glass, stained, and
looked at through the microscope. Even before digital computers became common, there have been attempts to automate the
analysis of the smear. My colleague Ewert
Bengtsson &lt;a href="http://urn.kb.se/resolve?urn=urn:nbn:se:uu:diva-116965"&gt;wrote his PhD thesis on the subject in 1977&lt;/a&gt;, and
is &lt;a href="http://dx.doi.org/10.1109/EMBC.2012.6347208"&gt;still publishing in the field today&lt;/a&gt;. This gives an idea of how hard it
is to replicate something that is quite easy, though time consuming, for a trained person. The solution, as is often the
case, was to change how the sample is prepared. Instead of smearing the sample on a microscope glass, liquid cytology
systems were invented that cleaned the sample (removing slime, blood cells, etc.), and produced a neat deposition of
cells on the glass such that they are nicely separated and not likely to overlap each other. Such a preparation makes
the automated image analysis much easier. However, these automated systems still do not produce a perfect result, and
therefore are only approved to be used &lt;em&gt;together&lt;/em&gt; with a trained cytologist. That is, the cytologist still needs to
review all the tests. This means that the Pap smear test has become more expensive, rather than cheaper (the
liquid-based sample preparation uses expensive consumables).&lt;/p&gt;
&lt;p&gt;But the cost is not the real problem, and this is why these new automated Pap test systems are used in practice. The
problem is that the probability that a sample is positive is quite low. That means that even a small bias towards the
positives will produce a huge amount of false positives. For example, assume one in a 1000 tested women has cervical
cancer, and that the system has a specificity of 90% (totally made up figures, I have no idea what these are in
practice). This would mean that about 100 perfectly healthy women would be diagnosed with cancer by the system, for
every one woman whose cancer is detected!&lt;/p&gt;
&lt;p&gt;I recently came
across &lt;a href="http://www.nytimes.com/2013/07/21/business/dissent-over-a-device-to-help-find-melanoma.html"&gt;an article in The New York Times&lt;/a&gt;
reporting on a device, &lt;a href="http://melasciences.com/melafind"&gt;MelaFind&lt;/a&gt;, that is designed to recognize melanoma. To me it
seems they did a lot of things right: the device takes images at various wavelengths, including some near-infrared, and
at various depths under the skin surface (i.e. it obtains information that the dermatologist does not have); they
trained the device on a database with 10,000 lesions (with biopsy information, from 40 different sites); etc. Yet look
at these three comments from the FDA panel that are reported in the article:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;[I am] concerned that a doctor could inadvertently use MelaFind on a non-melanoma skin cancer, receive a score
indicating that the spot was not irregular, and erroneously decide not to biopsy it.&lt;/p&gt;
&lt;p&gt;My concern with MelaFind is that it just says everything is positive.&lt;/p&gt;
&lt;p&gt;There is inadequate data to determine any true value added for MelaFind for use by a dermatologist or other provider.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Why are these FDA panellists so negative? The first comment is about wrong use of the device. Of course, MelaFind is
trained on a dataset of &amp;ldquo;clinically atypical cutaneous pigmented lesions with one or more clinical or historical
characteristics of melanoma,&amp;rdquo; and therefore will produce random output if an image taken is of anything else. If the
input is outside of the domain generated by the training set, all bets are off. This is valid concern, but not difficult
to avoid by limiting the use of MelaFind to dermatologists, as the FDA did. The second and third comments, on the other
hand, are what this blog post is about. As the article puts it: &amp;ldquo;[&amp;hellip;] a biostatistician [&amp;hellip;] compared the accuracy
of MelaFind in distinguishing non-melanomas to a hypothetical pregnancy test which, used on 100 nonpregnant women, would
mistakenly conclude that 90 of them were pregnant.&amp;rdquo; The problem is low specificity!&lt;/p&gt;
&lt;p&gt;Further reading
on &lt;a href="http://www.melafind.com/dermatologists/about-melafind#clinical-data"&gt;MelaFind&amp;rsquo;s dermatologist-only web pages&lt;/a&gt; (yes,
I had to actually claim I&amp;rsquo;m a dermatologist to get to those pages!), you can see the details of the study that the FDA
approval is based on. Apparently they collected a large group of patients, who together had 1632 lesions that were
suitable for the device to diagnose. Of these, 175 were melanomas or high-grade lesions (I&amp;rsquo;ll just call them all
melanomas for simplicity). That is, a little over 10% of the test set is positive, most of it is negative. MelaFind
detected 173 of 175 melanomas (98.3% sensitivity). This is a very good sensitivity (but of course no mention is made of
the dermatologists&amp;rsquo; sensitivity in this study, more on that later). However, the specificity was only 10.8%. That is, it
recognized only 157 negatives as negatives! MelaFind diagnosed as melanoma 1473 out of 1632 lesions shown to it (90.3%),
pretty close to just saying everything as positive. And thus, as the 3rd comment above said, is there are added value to
use the device?&lt;/p&gt;
&lt;p&gt;We have to compare MelaFind performance with that of dermatologists. In the study, dermatologists had a 5.6%
specificity. That is, they marked as melanoma even more of the lesions (though only 65 or so lesions more).
Surprisingly, there is no mention of the sensitivity of these dermatologists. I would guess they get 100%, otherwise
they would have reported it. Instead, they give some random statistics from another study that shows dermatologists only
detect 70–80% of melanomas. There is no way of comparing that study to this one, as the input to the study (the test
set) is most likely chosen very differently. And, given the clinical process, dermatologists are very much biased, as is
the device, to positives: everything that might be a melanoma is taken out an send to a pathologist; they don&amp;rsquo;t want to
run any risks of missing one. This guess of 100% sensitivity is also supported by the FDA&amp;rsquo;s approval specifically
stating that it is not intended to be used on lesions with a clinical diagnosis of melanoma or likely melanoma, and that
biopsy decision on MelaFind negative lesion is up to the dermatologist.&lt;/p&gt;
&lt;p&gt;So assuming dermatologists really had a 100% sensitivity, the study says that, if always following the device&amp;rsquo;s
recommendation, 65 fewer samples would have been biopsied, but two melanomas would not have been found. Is that a valid
trade-off? Most surely not. I wonder what the dermatologists&amp;rsquo; specificity would be if they would be a little bit less
cautious (i.e. lowering their sensitivity to that of MelaFind). Or conversely, what the specificity of MelaFind would be
if tuned to yield 100% sensitivity on this test set. In either of those cases, it would be possible to directly compare
the specificities. I would bet that in such a case the dermatologists would do much better than MelaFind. And thus the
comment regarding its added value is legitimate. In the article it says that &amp;ldquo;patients are paying $25 to $175 for the
first mole evaluation and around $25 for subsequent moles.&amp;rdquo; Is this a waste of money? I don&amp;rsquo;t think that the device
gives the patients a better diagnosis. If it just helps the dermatologist to do his/her job faster, why is the patient
paying more for the diagnosis, instead of less?&lt;/p&gt;
&lt;p&gt;I hope this does not sound too negative. I know a lot of things can be automated and improved with image analysis, even
in clinical settings. I truly believe we will have fully automatic diagnosis at some point in the not too distant
future (hey, &lt;a href="http://en.wikipedia.org/wiki/Leonard_McCoy" title="Dr. Leonard &amp;quot;Bones&amp;quot; McCoy, of Star Trek fame"&gt;Dr. McCoy&lt;/a&gt;
didn&amp;rsquo;t need to go through med school just to hold that device that diagnosed and cured all his patients, did he?). But
we&amp;rsquo;re not nearly there yet: we need to do more work on our ability to recognize wrong input (in this case the
non-cutaneous or non-pigmented lesions, the non-lesions, the patient&amp;rsquo;s shirt, etc.), and we need to do more on our
ability to generalize from examples. This is what sets the human eye–brain combo apart from anything else, natural or
engineered: we can take the context into account, we can adapt to environmental changes, and we generalize like there is
no tomorrow.&lt;/p&gt;</content><category term="criticism"></category><category term="diagnosis"></category><category term="medicine"></category><category term="pathology"></category><category term="sensitivity"></category><category term="specificity"></category></entry><entry><title>How did this get published?</title><link href="https://www.crisluengo.net/archives/512" rel="alternate"></link><published>2012-12-19T11:33:00-07:00</published><updated>2012-12-19T11:33:00-07:00</updated><author><name>Cris Luengo</name></author><id>tag:www.crisluengo.net,2012-12-19:/archives/512</id><summary type="html">&lt;p&gt;&amp;ldquo;How did this get published?&amp;rdquo; is a question I regularly ask myself when reading new papers coming out. I just came
across another one of these jewels, and because the topic is that of a previous blog post here, I thought I&amp;rsquo;d share my
frustration with you.&lt;/p&gt;
&lt;p&gt;The paper …&lt;/p&gt;</summary><content type="html">&lt;p&gt;&amp;ldquo;How did this get published?&amp;rdquo; is a question I regularly ask myself when reading new papers coming out. I just came
across another one of these jewels, and because the topic is that of a previous blog post here, I thought I&amp;rsquo;d share my
frustration with you.&lt;/p&gt;
&lt;p&gt;The paper is entitled &amp;ldquo;On Perceptually Consistent Image
Binarization&amp;rdquo; (&lt;a href="http://dx.doi.org/10.1109/LSP.2012.2226716"&gt;IEEE Signal Processing Letters 20(1):3:6, 2013&lt;/a&gt;), which
leads one to believe that this is an interesting paper related to segmentation or thresholding and visual perception.
The abstract, however, helpfully lets us know this is about error diffusion. And it promises a strong theoretical
foundation leading to perceptually consistent halftone
images. &lt;a href="/archives/355"&gt;I previously wrote about error diffusion here&lt;/a&gt;, so let&amp;rsquo;s look at what they did.&lt;/p&gt;
&lt;p&gt;The introduction doesn&amp;rsquo;t start very strongly:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Of various image binarization methods, error diffusion is a popular one and has been widely used in image printing
and display applications [6]. It was firstly introduced by Floyd and Steinberg and lately some other variations
have also been proposed.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;And that is it, no review whatsoever of the later variations. This is troubling, because this typically means that they
will only compare their new method to that very first method, and ignore all of the literature that came after. If you
read my previous blog post, you&amp;rsquo;ll know that error diffusion was introduced in 1975. That is nearly 40 years of research
that these authors are pretending never happened!&lt;/p&gt;
&lt;p&gt;The proposed scheme turns out to be the same as Floyd-Steinberg, but they also suggest the use of a larger window, as
Jarvis, Judice and Ninke did in 1976. Thus, this is a paper proposing yet another set of weights for the standard
algorithm. The promised theory is quite funny too, if you&amp;rsquo;re only somewhat familiar with diffusion. They start with heat
exchange (this is basic diffusion), and somewhere propose that&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Then, the amount of heat exchanged between the current pixel and its neighbours in unit time is in proportion to the
reciprocal of their distances, that is &lt;span class="math"&gt;&lt;svg style="width: 4.373em; height: 1.072em; vertical-align: -0.230em; " viewBox="0 -8.42 43.73 10.72"&gt;
&lt;title&gt;
\(\Delta Q \propto \nicefrac{1}{d}\)
&lt;/title&gt;
&lt;defs&gt;
&lt;path id='eq2-g14-49' d='M3.44 0V-.13C2.75-.14 2.61-.23 2.61-.65V-5.89L2.54-5.9L.97-5.11V-4.99C1.07-5.03 1.17-5.07 1.21-5.08C1.36-5.14 1.51-5.18 1.6-5.18C1.78-5.18 1.86-5.05 1.86-4.77V-.81C1.86-.52 1.79-.32 1.65-.24C1.52-.17 1.4-.14 1.03-.13V0H3.44Z'/&gt;
&lt;path id='eq2-g7-38' d='M5.83 .43L5.7 .33C5.21 .84 4.86 1 4.23 1C4.13 1 4.05 .99 3.98 .98L2.35 .64L2.22 .63C2.2 .64 2.18 .64 2.18 .64H1.97L2.44 .14C3.09 .1 3.4 .02 3.87-.24C5.2-.93 6.11-2.38 6.11-3.78C6.11-4.96 5.27-5.82 4.11-5.82C3.44-5.82 2.72-5.5 2.04-4.93C1.09-4.11 .52-3 .52-1.93C.52-1.22 .78-.64 1.23-.27C1.48-.08 1.67 .01 2.06 .1C1.27 .8 1.19 .87 .52 1.35L.6 1.48C.93 1.29 1.26 1.21 1.61 1.21C1.78 1.21 2.04 1.25 2.42 1.36C2.95 1.51 3.42 1.59 3.75 1.59C4.23 1.59 4.83 1.36 5.28 1.02C5.49 .86 5.61 .73 5.83 .43ZM5.19-4.19C5.19-3.29 4.8-2.04 4.25-1.23C3.76-.51 3.21-.15 2.56-.15C1.84-.15 1.44-.67 1.44-1.6C1.44-2.41 1.85-3.68 2.37-4.44C2.86-5.18 3.41-5.53 4.06-5.53C4.76-5.53 5.19-5.02 5.19-4.19Z'/&gt;
&lt;path id='eq2-g7-51' d='M4.15-.88L4.04-.97C3.56-.42 3.48-.35 3.33-.35C3.24-.35 3.17-.42 3.17-.52C3.17-.66 3.44-1.69 3.74-2.67L4.6-5.92L4.56-5.97C4.1-5.87 3.78-5.82 3.22-5.76V-5.62C3.7-5.6 3.76-5.57 3.76-5.39C3.76-5.27 3.76-5.24 3.63-4.78L3.25-3.35C3.18-3.71 3.02-3.85 2.68-3.85C1.55-3.85 .13-2.21 .13-.9C.13-.28 .48 .1 1.05 .1C1.64 .1 2.03-.18 2.62-1.06C2.52-.62 2.51-.48 2.51-.28C2.51-.04 2.65 .11 2.87 .11C3.24 .11 3.7-.24 4.15-.88ZM3.11-3.15C3.11-1.83 2.2-.32 1.4-.32C1.09-.32 .89-.55 .89-.9C.89-1.62 1.33-2.64 1.9-3.25C2.14-3.49 2.44-3.65 2.68-3.65C2.69-3.65 2.71-3.65 2.72-3.65C2.98-3.63 3.11-3.47 3.11-3.15Z'/&gt;
&lt;path id='eq2-g4-47' d='M7.25-4.88C7-5.11 6.68-5.22 6.35-5.22C5.37-5.22 4.72-4.28 4.22-3.56C3.75-4.45 3.28-5.24 2.14-5.24C.93-5.24 .33-3.8 .33-2.76C.33-1.83 .74-.75 1.83-.75C2.87-.75 3.48-1.64 3.95-2.44C4.48-1.54 4.85-.74 6.04-.74C6.46-.74 6.82-.94 7.12-1.23L6.96-1.43C6.74-1.21 6.44-1.14 6.16-1.14C5.22-1.14 4.75-2.51 4.38-3.22C4.79-3.92 5.4-4.65 6.28-4.65C6.52-4.65 6.72-4.49 6.86-4.31L7.25-4.88ZM3.79-2.78C3.45-2.16 2.91-1.38 2.12-1.38C1.26-1.38 .92-2.67 .92-3.35C.92-4.01 1.19-4.8 1.99-4.8C2.94-4.8 3.47-3.5 3.79-2.78Z'/&gt;
&lt;path id='eq2-g4-157' d='M.74 2.3H1.36L4.74-8.42H4.12L.74 2.3Z'/&gt;
&lt;use id='eq2-g10-38' xlink:href='#eq2-g7-38' transform='scale(1.36)'/&gt;
&lt;path id='eq2-g1-1' d='M7.36 0L4.03-8.04H3.82L.29 0H7.36ZM5.97-.5H1.07L3.62-6.26L5.97-.5Z'/&gt;
&lt;/defs&gt;
&lt;g id='eq2-page1'&gt;
&lt;use x='0' y='0' xlink:href='#eq2-g1-1'/&gt;
&lt;use x='7.57' y='0' xlink:href='#eq2-g10-38'/&gt;
&lt;use x='20.09' y='0' xlink:href='#eq2-g4-47'/&gt;
&lt;use x='31.02' y='-2.08' xlink:href='#eq2-g14-49'/&gt;
&lt;use x='34.07' y='0' xlink:href='#eq2-g4-157'/&gt;
&lt;use x='39.13' y='0' xlink:href='#eq2-g7-51'/&gt;
&lt;/g&gt;
&lt;/svg&gt;&lt;/span&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This comes out of nowhere, without references or proof, of course. And we all know that the solution to the heat
equation (basic, isotropic diffusion) is a Gaussian. That is, heat exchanged between two points is proportional to
&lt;span class="math"&gt;&lt;svg style="width: 4.468em; height: 1.283em; vertical-align: -0.259em; " viewBox="0 -10.24 44.68 12.83"&gt;
&lt;title&gt;
\(\exp(-d^2)\)
&lt;/title&gt;
&lt;defs&gt;
&lt;path id='eq1-g8-50' d='M4.15-1.2L4.04-1.24C3.71-.74 3.6-.66 3.21-.66H1.12L2.59-2.2C3.36-3.01 3.7-3.68 3.7-4.36C3.7-5.23 3-5.9 2.09-5.9C1.61-5.9 1.15-5.71 .83-5.36C.55-5.07 .42-4.79 .27-4.17L.45-4.12C.8-4.98 1.12-5.26 1.72-5.26C2.45-5.26 2.95-4.76 2.95-4.03C2.95-3.35 2.55-2.53 1.82-1.76L.26-.1V0H3.67L4.15-1.2Z'/&gt;
&lt;path id='eq1-g8-101' d='M3.7-1.37L3.56-1.43C3.14-.77 2.77-.52 2.21-.52C1.73-.52 1.36-.74 1.11-1.21C.93-1.55 .86-1.86 .85-2.42H3.54C3.47-2.99 3.38-3.24 3.16-3.52C2.9-3.83 2.5-4.02 2.04-4.02C.96-4.02 .22-3.14 .22-1.87C.22-.66 .85 .09 1.85 .09C2.69 .09 3.34-.43 3.7-1.37ZM2.65-2.7H.86C.96-3.39 1.26-3.7 1.79-3.7S2.53-3.46 2.65-2.7Z'/&gt;
&lt;path id='eq1-g8-112' d='M4.11-2.16C4.11-3.24 3.49-4.02 2.65-4.02C2.16-4.02 1.77-3.8 1.39-3.33V-4L1.34-4.02C.86-3.83 .56-3.72 .08-3.57V-3.43C.16-3.44 .22-3.44 .3-3.44C.59-3.44 .66-3.35 .66-2.94V1.14C.66 1.6 .56 1.69 .04 1.75V1.9H2.16V1.74C1.5 1.73 1.39 1.63 1.39 1.08V-.29C1.69 0 1.9 .09 2.27 .09C3.3 .09 4.11-.89 4.11-2.16ZM3.35-1.82C3.35-.85 2.93-.19 2.3-.19C1.89-.19 1.39-.51 1.39-.77V-2.92C1.39-3.18 1.88-3.49 2.28-3.49C2.93-3.49 3.35-2.83 3.35-1.82Z'/&gt;
&lt;path id='eq1-g8-120' d='M4.18 0V-.13C3.91-.13 3.74-.27 3.47-.66L2.35-2.37L3.07-3.42C3.24-3.65 3.5-3.79 3.78-3.8V-3.93H2.4V-3.8C2.66-3.78 2.75-3.73 2.75-3.61C2.75-3.5 2.65-3.31 2.43-3.04C2.38-2.99 2.28-2.83 2.17-2.66L2.04-2.83C1.8-3.2 1.64-3.49 1.64-3.61C1.64-3.73 1.76-3.79 2.02-3.8V-3.93H.21V-3.8H.29C.55-3.8 .69-3.69 .96-3.28L1.78-2.02L.79-.58C.52-.22 .44-.16 .15-.13V0H1.41V-.13C1.17-.13 1.07-.17 1.07-.29C1.07-.34 1.13-.47 1.24-.65L1.93-1.72L2.73-.5C2.76-.45 2.78-.39 2.78-.34C2.78-.18 2.72-.15 2.43-.13V0H4.18Z'/&gt;
&lt;path id='eq1-g4-51' d='M5.66-1.2L5.51-1.32C4.86-.57 4.74-.48 4.54-.48C4.42-.48 4.32-.57 4.32-.71C4.32-.91 4.69-2.3 5.1-3.64L6.28-8.08L6.22-8.13C5.59-8 5.16-7.93 4.39-7.86V-7.66C5.05-7.63 5.13-7.6 5.13-7.35C5.13-7.18 5.12-7.15 4.95-6.52L4.43-4.56C4.34-5.06 4.12-5.25 3.66-5.25C2.11-5.25 .18-3.01 .18-1.23C.18-.38 .66 .13 1.43 .13C2.24 .13 2.76-.25 3.57-1.44C3.44-.85 3.42-.66 3.42-.38C3.42-.06 3.61 .15 3.92 .15C4.42 .15 5.05-.33 5.66-1.2ZM4.24-4.3C4.24-2.49 3-.44 1.91-.44C1.49-.44 1.21-.75 1.21-1.23C1.21-2.22 1.81-3.6 2.6-4.43C2.92-4.76 3.32-4.98 3.66-4.98C3.67-4.98 3.69-4.98 3.7-4.98C4.06-4.95 4.24-4.73 4.24-4.3Z'/&gt;
&lt;path id='eq1-g1-0' d='M6.84-2.73V-3.39H.74V-2.73H6.84Z'/&gt;
&lt;path id='eq1-g1-185' d='M3.51-8.54C1.79-7.42 .57-5.49 .57-3.06C.57-.85 1.83 1.39 3.48 2.41L3.62 2.22C2.05 .98 1.6-.46 1.6-3.1C1.6-5.74 2.08-7.11 3.62-8.35L3.51-8.54Z'/&gt;
&lt;path id='eq1-g1-186' d='M.45-8.54L.35-8.35C1.88-7.11 2.37-5.74 2.37-3.1C2.37-.46 1.92 .98 .35 2.22L.49 2.41C2.13 1.39 3.39-.85 3.39-3.06C3.39-5.49 2.18-7.42 .45-8.54Z'/&gt;
&lt;use id='eq1-g11-101' xlink:href='#eq1-g8-101' transform='scale(1.36)'/&gt;
&lt;use id='eq1-g11-112' xlink:href='#eq1-g8-112' transform='scale(1.36)'/&gt;
&lt;use id='eq1-g11-120' xlink:href='#eq1-g8-120' transform='scale(1.36)'/&gt;
&lt;/defs&gt;
&lt;g id='eq1-page1'&gt;
&lt;use x='0' y='0' xlink:href='#eq1-g11-101'/&gt;
&lt;use x='4.89' y='0' xlink:href='#eq1-g11-120'/&gt;
&lt;use x='10.87' y='0' xlink:href='#eq1-g11-112'/&gt;
&lt;use x='17.44' y='0' xlink:href='#eq1-g1-185'/&gt;
&lt;use x='21.9' y='0' xlink:href='#eq1-g1-0'/&gt;
&lt;use x='29.8' y='0' xlink:href='#eq1-g4-51'/&gt;
&lt;use x='36.4' y='-4.34' xlink:href='#eq1-g8-50'/&gt;
&lt;use x='41.29' y='0' xlink:href='#eq1-g1-186'/&gt;
&lt;/g&gt;
&lt;/svg&gt;&lt;/span&gt;. The weights proposed are given only as an equation, and they demonstrate with 4 neighbours (as did
Floyd-Steinberg) or with 10 (two neighbours less than Jarvis-Judice-Ninke).&lt;/p&gt;
&lt;p&gt;Now comes the kicker! The experimental results is always the place where I get most frustrated. Apparently we don&amp;rsquo;t
teach how to do science any more. This is the most important part of our jobs, but instead most papers in image
processing use the experimental results section to show the extent of our ineptitude. Worse even than I feared, the
&amp;ldquo;new&amp;rdquo; method is compared to thresholding! This is the first paragraph of the results section:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;To evaluate the performance of the proposed scheme, experiments are implemented. [&lt;em&gt;wow! how clever!&lt;/em&gt;] Partial results
on some test images are given in Figs. 3­&amp;ndash;6, where Fig. 3 are the original test images, Fig. 4 shows the binarized
results of traditional fixed-threshold scheme, Figs. 5 and 6 are the results of the proposed scheme with &lt;em&gt;d&lt;/em&gt;&lt;sub&gt;s&lt;/sub&gt;=√2
and &lt;em&gt;d&lt;/em&gt;&lt;sub&gt;s&lt;/sub&gt;=√5 [&lt;em&gt;these are the two neighbourhood sizes&lt;/em&gt;] by using raster scan order, respectively.
From the results one can see that, compared with the traditional fixed-threshold scheme, the visual quality of the
binarized images with our scheme can be greatly improved. [&lt;em&gt;!!!&lt;/em&gt;]&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;They are actually saying that visual quality of error diffusion is better than that of thresholding!&lt;/p&gt;
&lt;p&gt;The next paragraph compares, visually, on 4 images, the result of the &amp;ldquo;new&amp;rdquo; method with those of Floyd-Steinberg (1975)
and Jarvis-Judice-Ninke (1976), leading to the conclusion that it is difficult to tell the difference between the
methods (guess why!). Sadly, the authors chose not to show the results of these old methods on two of the images that
they showed in the previous paragraph. This probably means that these images looked better with the old methods!
Finally, the third paragraph of the experimental section does an &amp;ldquo;objective&amp;rdquo; comparison, with actual numbers. They
blurred the dithered images and compared them with the original images using the PSNR
measure. &lt;a href="/archives/490"&gt;Of course, as I wrote before, the PSNR measure is pointless.&lt;/a&gt; But what is worse is that the
differences with Jarvis-Judice-Ninke are mostly insignificant: 28.018 vs 28.079, etc.&lt;/p&gt;
&lt;p&gt;To further embarrass themselves to the readers of this blog, they blurred the image by filtering &amp;ldquo;three times with the
3×3 Gaussian low-pass filter.&amp;rdquo; As you all
know, &lt;a href="/archives/22"&gt;repeated applications of the Gaussian filter are equivalent to a wider Gaussian filter&lt;/a&gt;,
and &lt;a href="/archives/150"&gt;3×3 pixels is not enough to correctly represent a Gaussian filter&lt;/a&gt;. I am afraid that these people
fell into the trap put in front of them by MATLAB, which by default generates a 3×3 mask for a Gaussian filter.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve run the algorithms with the proposed weights on &lt;a href="/archives/355"&gt;the test image I used previously&lt;/a&gt;. These are the
results:&lt;/p&gt;
&lt;p class="centering"&gt;&lt;img alt="Result with 4-pixel neighbourhood" src="/images/dither_bad1.png"&gt;&lt;/p&gt;
&lt;p class="centering"&gt;&lt;img alt="Result with 10-pixel neighbourhood" src="/images/dither_bad2.png"&gt;&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ll copy the Floyd-Steinberg (1975), the Zhou-Fang (2003) and the Chang-Alain-Ostromoukhov (2009) results from the
previous post for comparison:&lt;/p&gt;
&lt;p class="centering"&gt;&lt;img alt="Result of Floyd-Steinberg" src="/images/dither_floydsteinberg.png"&gt;&lt;/p&gt;
&lt;p class="centering"&gt;&lt;img alt="Result of Zhou-Fang " src="/images/dither_zhoufang.png"&gt;&lt;/p&gt;
&lt;p class="centering"&gt;&lt;img alt="Result of Chang-Alain-Ostromoukhov" src="/images/dither_structure.png"&gt;&lt;/p&gt;
&lt;p&gt;How did this paper get published?&lt;/p&gt;</content><category term="criticism"></category><category term="bad science"></category><category term="dither"></category><category term="error diffusion"></category></entry><entry><title>Scientific writing and the pronoun I</title><link href="https://www.crisluengo.net/archives/421" rel="alternate"></link><published>2011-10-05T17:08:00-06:00</published><updated>2011-10-05T17:08:00-06:00</updated><author><name>Cris Luengo</name></author><id>tag:www.crisluengo.net,2011-10-05:/archives/421</id><summary type="html">&lt;p&gt;Why are scientists so scared of writing their statements in the first person? Open any journal, and look for the word
&amp;ldquo;I&amp;rdquo;. Chances are, you won&amp;rsquo;t find it. You&amp;rsquo;ll see article authors jump through hoops just to avoid this word. As if it were
dirty, illegal. For example …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Why are scientists so scared of writing their statements in the first person? Open any journal, and look for the word
&amp;ldquo;I&amp;rdquo;. Chances are, you won&amp;rsquo;t find it. You&amp;rsquo;ll see article authors jump through hoops just to avoid this word. As if it were
dirty, illegal. For example, instead of a normal, complete sentence like &amp;ldquo;I found existing methods to be insufficiently
accurate,&amp;rdquo; you&amp;rsquo;ll find the sentence &amp;ldquo;Existing methods were found to be insufficiently accurate.&amp;rdquo; This leaves the most
important thing out: who found them insufficiently accurate? Is this a generally known thing? Does the whole world share
this opinion? Was it the dog that didn&amp;rsquo;t like the method? Why do they shy away from the word &amp;ldquo;I&amp;rdquo;? Does it make science
less objective?&lt;/p&gt;
&lt;p&gt;In the example above, the author tried to avoid subjectiveness by rewriting the sentence and leaving out the active
subject. As if that makes the concept less subjective. It was the author, after all, who evaluated and discarded these
methods. The author didn&amp;rsquo;t like them. This is a subjective evaluation. The only way to avoid subjectiveness is to devise
an experiment, and prove that existing methods do not meet the required accuracy requirement. Lacking that, the
statement is subjective, and hiding this fact is misleading.&lt;/p&gt;
&lt;p&gt;Scientists are subjective, this is no secret. They are human, after all. This means that, no matter what people want to
believe, the scientific process is subjective as well. A scientists chooses what to study, and his (or her) opinions
influence which of his (her) results are published, for example. This leads to publication bias, of course, but
otherwise does not taint the objectiveness of the scientific results. As long as these scientists are honest,
and &lt;a href="http://news.sciencemag.org/scienceinsider/2011/09/dutch-university-sacks-social.html"&gt;don&amp;rsquo;t invent data&lt;/a&gt;, or misuse
statistics, their opinions should not influence the outcome of their experiments.&lt;/p&gt;
&lt;p&gt;But if it is subjectiveness that these authors are scared of, why is it less of a problem to use the word &amp;ldquo;we&amp;rdquo;? Is it
the implied consensus? It is no longer the opinion of a single person, but that of a group of people, and thus more
objective in some way. This leads to strange things, like the editors of IEEE replacing all occurrences of &amp;ldquo;I&amp;rdquo; with &amp;ldquo;we&amp;rdquo;
in &lt;a href="http://dx.doi.org/10.1109/TIP.2010.2044959"&gt;a recent paper of mine&lt;/a&gt; (if there is only one author, who is the &amp;ldquo;we&amp;rdquo;
in &amp;ldquo;First we will give a short description of&amp;hellip;&amp;rdquo;?). There&amp;rsquo;s a famous quote of Mark Twain that is relevant here: &amp;ldquo;Only
kings, presidents, editors, and people with tapeworms have the right to use the editorial &amp;lsquo;we.&amp;rsquo;&amp;ldquo;&lt;/p&gt;
&lt;p&gt;Interestingly enough, this fear of the pronoun &amp;ldquo;I&amp;rdquo; is rather recent. Einstein, at the beginning of the 20th century,
wrote things like &amp;ldquo;It is possible that the movements to be discussed here are identical with the so-called &amp;lsquo;Brownian
molecular motion&amp;rsquo;; however, the information available to me regarding the latter is so lacking in precision, that I can
form no judgment in the matter&amp;rdquo; (in the first paragraph of &amp;ldquo;On the movement of small particles suspended in stationary
liquid&amp;hellip;&amp;rdquo;, a translation of which can be
had &lt;a href="http://users.physik.fu-berlin.de/~kleinert/files/eins_brownian.pdf"&gt;here&lt;/a&gt;). Going back in time to the 17th century,
we can find even more extensive use of the first person pronoun. Newton, for example, gives a good example of how
experiment-based papers should be written (in my opinion): &amp;ldquo;[&amp;hellip;] I became surprised to see them in an oblong form;
which, according to the received laws of Refraction, I expected should have been circular&amp;rdquo; (from
&lt;a href="http://psych-s1.psy.vanderbilt.edu/faculty/blaker/343_S2007/PDFs/Newton_1672.pdf"&gt;&amp;ldquo;A new theory of light and colors&amp;rdquo;&lt;/a&gt;).
This is so much more vivid and pleasant to read than &amp;ldquo;they had an oblong form, not circular as predicted by laws of
refraction.&amp;rdquo; But maybe the beginning of that same sentence could have been redacted out, as it certainly does not relate
in any way to the science being described: &amp;ldquo;It was at first a very pleasing divertisement, to view the vivid and intense
colours produced thereby [&amp;hellip;].&amp;rdquo; Nonetheless, this paper would have been much more boring to read had it been written
today.&lt;/p&gt;
&lt;p&gt;So I wonder, why did this openness about the subjectivity of the scientific process disappear? When did they start to
become afraid of &amp;ldquo;I&amp;rdquo;? Why? Please weigh in by adding a comment, I&amp;rsquo;d love to hear your opinions!&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Edit&lt;/p&gt;
&lt;p&gt;I was just made aware of &lt;a href="http://dx.doi.org/10.1111/j.0030-1299.2007.15674.x"&gt;this publication&lt;/a&gt; (there&amp;rsquo;s a
scanned PDF available &lt;a href="http://www.afrc.uamont.edu/whited/Sand-Jensen%202007.pdf"&gt;here&lt;/a&gt; if you don&amp;rsquo;t have access
to the version at Wiley&amp;rsquo;s online library). It doesn&amp;rsquo;t talk at all about personal pronouns, but it does criticize
the boring tone of scientific writing nowadays. Nice read!&lt;/p&gt;
&lt;/div&gt;</content><category term="criticism"></category><category term="scientific paper"></category><category term="scientist"></category><category term="style"></category><category term="writing"></category></entry><entry><title>Gaussian filtering with the Image Processing Toolbox</title><link href="https://www.crisluengo.net/archives/150" rel="alternate"></link><published>2009-10-06T22:28:00-06:00</published><updated>2009-10-06T22:28:00-06:00</updated><author><name>Cris Luengo</name></author><id>tag:www.crisluengo.net,2009-10-06:/archives/150</id><summary type="html">&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Edit May 2018&lt;/p&gt;
&lt;p&gt;Since publishing this post, the MATLAB Image Processing Toolbox has added the
function &lt;a href="https://www.mathworks.com/help/images/ref/imgaussfilt.html"&gt;&lt;code&gt;imgaussfilt&lt;/code&gt;&lt;/a&gt; that correctly applies a
Gaussian smoothing filter. For Gaussian derivatives, the recommendations here still apply.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Edit July 2024&lt;/p&gt;
&lt;p&gt;I just learned that &lt;code&gt;imgaussfilt&lt;/code&gt; uses a truncation of 2 by default (i.e. it …&lt;/p&gt;&lt;/div&gt;</summary><content type="html">&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Edit May 2018&lt;/p&gt;
&lt;p&gt;Since publishing this post, the MATLAB Image Processing Toolbox has added the
function &lt;a href="https://www.mathworks.com/help/images/ref/imgaussfilt.html"&gt;&lt;code&gt;imgaussfilt&lt;/code&gt;&lt;/a&gt; that correctly applies a
Gaussian smoothing filter. For Gaussian derivatives, the recommendations here still apply.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Edit July 2024&lt;/p&gt;
&lt;p&gt;I just learned that &lt;code&gt;imgaussfilt&lt;/code&gt; uses a truncation of 2 by default (i.e. it computes &lt;code&gt;cutoff = ceil(2*sigma)&lt;/code&gt;).
This is not sufficiently large for most applications, see &lt;a href="/archives/695"&gt;this other post&lt;/a&gt;.
There&amp;rsquo;s a &lt;code&gt;'FilterSize'&lt;/code&gt; name-value argument that should be used with this function to set the correct filter
size, computed as shown in this post.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;If you don&amp;rsquo;t use &lt;a href="https://diplib.org/"&gt;DIPimage&lt;/a&gt;, you probably use
MATLAB&amp;rsquo;s &lt;a href="http://www.mathworks.com/products/image/"&gt;Image Processing Toolbox&lt;/a&gt;. This toolbox makes it really easy to do
convolutions with a &lt;a href="/archives/22"&gt;Gaussian&lt;/a&gt; in the wrong way. On three accounts. The
function &lt;a href="http://www.mathworks.com/help/images/ref/fspecial.html"&gt;&lt;code&gt;fspecial&lt;/code&gt;&lt;/a&gt; is used to create a convolution kernel for
a Gaussian filter. This kernel is 2D. That&amp;rsquo;s the first problem. The other two problems are given by the default values
of its parameters. The default value for the kernel size is &lt;code&gt;[3 3]&lt;/code&gt;. The default value for the σ (sigma) is 0.5. σ=0.5
is too small for a Gaussian kernel. When a kernel this small is sampled, too much aliasing occurs. Depending on who you
listen to, the smallest σ you can use is either 0.8 or 1.0. The value of σ dictates the shape of the kernel, but it also
determines its size: truncating the Gaussian kernel at &lt;code&gt;[3 3]&lt;/code&gt; pixels creates a sharp border which will cause unwanted
artifacts in the output image. All the good properties of the Gaussian filter will be lost. You have to cut off the
Gaussian at a point where it is close to zero. This happens around 3σ. This means that the size of the Gaussian kernel
should be 6σ (cut off at 3σ on ether size of the origin). Or if you need really high numerical accuracy, you can make
this larger, say 10σ. These last two issues are easy to take care of:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;single&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;imread&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;cameraman.tif&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="n"&gt;sigma&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;cutoff&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;ceil&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;sigma&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;fspecial&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;gaussian&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;cutoff&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;sigma&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;conv2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;same&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;However, this does not solve the first issue: the filter &lt;code&gt;h&lt;/code&gt; is two-dimensional, but the Gaussian is separable! That
it&amp;rsquo;s separable means that we can save a lot of computation by convolving with a one-dimensional Gaussian along the
x-axis and then with another along the y-axis. You can accomplish this with:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;fspecial&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;gaussian&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;cutoff&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="n"&gt;sigma&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;% 1D filter&lt;/span&gt;
&lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;conv2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;same&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The separable Gaussian filter is always faster to compute when implemented as two one-dimensional filters than when
implemented as one two-dimensional filter. Taking σ=1, this means we do 7+7=14 multiplications per pixel instead of
7×7=49 multiplications per pixel. The savings are increasingly important for larger kernels. With σ=5 this translates to
62 vs 961 multiplications.&lt;/p&gt;
&lt;p&gt;Finally, a Gaussian derivative should not be implemented like so:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;fspecial&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;gaussian&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;cutoff&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="n"&gt;sigma&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;conv2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;same&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;diff&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Nor like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;fspecial&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;gaussian&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;cutoff&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="n"&gt;sigma&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;dh&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;diff&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;conv2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dh&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;same&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Computing the finite difference approximation to the derivative of a smoothed image is the same as convolving with the
finite difference approximation to the derivative of the Gaussian. As discussed &lt;a href="/archives/22"&gt;earlier in this blog&lt;/a&gt;,
the advantage of computing Gaussian derivatives is lost when implemented this way. Instead, compute the exact derivative
of the Gaussian, and convolve with that:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;fspecial&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;gaussian&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;cutoff&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="n"&gt;sigma&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;dh&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;.*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;cutoff&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;cutoff&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;sigma&lt;/span&gt;^&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;conv2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dh&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;same&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Also note that, because the derivative of the Gaussian goes to zero slightly slower than the Gaussian itself, it is
worthwhile to increase the value of &lt;code&gt;cutoff&lt;/code&gt; to at least &lt;code&gt;ceil(3.5*sigma)&lt;/code&gt;.&lt;/p&gt;</content><category term="criticism"></category><category term="derivative"></category><category term="filtering"></category><category term="Gaussian"></category><category term="gradient"></category><category term="Image Processing Toolbox"></category><category term="separable"></category><category term="smoothing"></category></entry><entry><title>DIPimage issues that I can't solve</title><link href="https://www.crisluengo.net/archives/88" rel="alternate"></link><published>2009-08-25T11:26:00-06:00</published><updated>2009-08-25T11:26:00-06:00</updated><author><name>Cris Luengo</name></author><id>tag:www.crisluengo.net,2009-08-25:/archives/88</id><summary type="html">&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Edit December 2018&lt;/p&gt;
&lt;p&gt;Over the past two years &lt;a href="/archives/874"&gt;I&amp;rsquo;ve been working on DIPimage 3&lt;/a&gt;, an updated version of
DIPimage that is based on a rewritten DIPlib. Just about all of the issues discussed in this blog post have been
resolved there, with the exception of the &lt;code&gt;end&lt;/code&gt; operator, which …&lt;/p&gt;&lt;/div&gt;</summary><content type="html">&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Edit December 2018&lt;/p&gt;
&lt;p&gt;Over the past two years &lt;a href="/archives/874"&gt;I&amp;rsquo;ve been working on DIPimage 3&lt;/a&gt;, an updated version of
DIPimage that is based on a rewritten DIPlib. Just about all of the issues discussed in this blog post have been
resolved there, with the exception of the &lt;code&gt;end&lt;/code&gt; operator, which will now do the wrong thing if used in curly braces
(tensor indexing), and the limitation to the order of spatial and tensor indexing. We incurred a few backwards
compatibility breaks, but it was necessary for the long-term health of the toolbox.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;There are a few things in DIPimage that I&amp;rsquo;m annoyed with but can&amp;rsquo;t solve. Some of these are caused by the limitations of
the MATLAB interpreter, and some are caused by my own poor design choices. DIPimage evolved over time to do things that
I hadn&amp;rsquo;t at first even thought about, such as processing color images. Tensor and color images were &amp;ldquo;tagged on&amp;rdquo;, if you
will, on top of the &lt;code&gt;dip_image&lt;/code&gt; object, introducing some oddities and inconsistencies. To fix these up we would need to
change existing behavior, which we don&amp;rsquo;t want to do because it would break too much existing code. This blog entry is
about the few weird things with the &lt;code&gt;dip_image&lt;/code&gt; object and how to work around them.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;dip_image&lt;/code&gt; object was born to contain only a single grey-value object. Pretty soon it was extended to contain
multiple, unrelated images (mirroring DIPlib&amp;rsquo;s &lt;code&gt;dip_ImageArray&lt;/code&gt; structure). It seemed logical to me to distinguish a
single image and an array of images, even though to MATLAB they are the same object, so I overloaded the &lt;code&gt;isa&lt;/code&gt;
and &lt;code&gt;class&lt;/code&gt; methods to make this distinction artificially. When there is more than one image in the &lt;code&gt;dip_image&lt;/code&gt; object,
it reports itself as an object of class &lt;code&gt;dip_image_array&lt;/code&gt;. This caused a few problems when we introduced tensor (and
color) images. As they say, hindsight is always 20-20. Now I wish I had implemented image arrays as a separate class, or
even simply as a cell array with &lt;code&gt;dip_image&lt;/code&gt; objects.&lt;/p&gt;
&lt;h2&gt;Indexing into a &lt;code&gt;dip_image&lt;/code&gt; or a &lt;code&gt;dip_image_array&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Indexing into a &lt;code&gt;dip_image_array&lt;/code&gt; is done using braces: &lt;code&gt;A{1}&lt;/code&gt;; indexing into a &lt;code&gt;dip_image&lt;/code&gt; is done using
brackets: &lt;code&gt;A(20)&lt;/code&gt;. Because of a limitation of the MATLAB parser, it is only possible to combine these two indices by
putting the braces before the brackets: &lt;code&gt;A{1}(20)&lt;/code&gt;. This is not so bad if you consider the images in the array to be
unrelated: first you select image number 1, then you select pixel 20 in that image. But when we introduced the concept
of tensor images, this limitation became frustrating. In a tensor image each pixel is a matrix. This is represented as
a &lt;code&gt;dip_image_array&lt;/code&gt; where each image has the same size, and contains the data for one of the tensor elements. For
example, an RGB image is a tensor image with a 3-element vector at each pixel. The first image in the &lt;code&gt;dip_image_array&lt;/code&gt;
is the red channel, the second is green, the third is blue. In such an image, &lt;code&gt;A(20)&lt;/code&gt; is a tensor (in this example an
RGB triplet). It would sometimes make more sense to index a tensor element by &lt;code&gt;A(20){1}&lt;/code&gt; rather than &lt;code&gt;A{1}(20)&lt;/code&gt;. But it
generates an error when you type it in, and there&amp;rsquo;s nothing I can do about that.&lt;/p&gt;
&lt;h2&gt;Methods overloaded for &lt;code&gt;dip_image&lt;/code&gt; and &lt;code&gt;dip_image_array&lt;/code&gt; objects&lt;/h2&gt;
&lt;p&gt;Even worse is the way that the functions &lt;code&gt;size&lt;/code&gt;, &lt;code&gt;length&lt;/code&gt;, &lt;code&gt;ndims&lt;/code&gt;, &lt;code&gt;numel&lt;/code&gt; and &lt;code&gt;end&lt;/code&gt; work. When the object is of
type &lt;code&gt;dip_image&lt;/code&gt;, they work on the image, and when the object is of type &lt;code&gt;dip_image_array&lt;/code&gt; they work on the array, not
the images inside. This made a little bit of sense initially, since it was assumed that the images inside the array were
unrelated. But with a color image &lt;code&gt;A&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nb"&gt;size&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;colorspace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;grey&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nb"&gt;size&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="output highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="go"&gt;ans =&lt;/span&gt;
&lt;span class="go"&gt;     [3,1]&lt;/span&gt;

&lt;span class="go"&gt;ans =&lt;/span&gt;
&lt;span class="go"&gt;     [256,256]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In the same way, &lt;code&gt;size(A{1})&lt;/code&gt; would return [256,256] and &lt;code&gt;size(A{1:2})&lt;/code&gt; would return &lt;code&gt;[2,1]&lt;/code&gt;. Needless to say, this
has lead to some hard-to-find bugs.&lt;/p&gt;
&lt;p&gt;It is possible to get around this issue by using only the functions &lt;code&gt;imsize&lt;/code&gt; and &lt;code&gt;imarsize&lt;/code&gt; for the image size and the
image array size, respectively. &lt;code&gt;length(A)&lt;/code&gt; should be written as &lt;code&gt;max(imsize(A))&lt;/code&gt;, and &lt;code&gt;ndims(A)&lt;/code&gt; as &lt;code&gt;length(imsize(A))&lt;/code&gt;.
&lt;code&gt;numel&lt;/code&gt; always returns 1. This was implemented to circumvent a bug in MATLAB 6 that broke the indexing (I don&amp;rsquo;t know
if this was fixed in later versions). &lt;code&gt;numel(A)&lt;/code&gt; should be written as &lt;code&gt;prod(imsize(A))&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Finally, the &lt;code&gt;end&lt;/code&gt; operator is the worst of the bunch, because I keep using it without thinking about it, and it always
takes me a while to find the cause of the bug. Also, the workaround is rather ugly. Like &lt;code&gt;size&lt;/code&gt;, &lt;code&gt;end&lt;/code&gt; uses the image
size if there is only one image in the object, but uses the array size if there is more than one image.
Thus, &lt;code&gt;A(0:2:end,:)&lt;/code&gt; works perfectly well when &lt;code&gt;A&lt;/code&gt; is a grey-value image, but doesn&amp;rsquo;t do what you&amp;rsquo;d expect if &lt;code&gt;A&lt;/code&gt; is a
tensor image. The workaround again is using &lt;code&gt;imsize&lt;/code&gt;: &lt;code&gt;A(0:2:imsize(A,1)-1,:)&lt;/code&gt;. Ugly, no? The reason for this issue is
that MATLAB does not report to the overloaded &lt;code&gt;end&lt;/code&gt; method whether it is invoked in brackets or braces. The &lt;code&gt;end&lt;/code&gt; method
existed before cell arrays and braces indexing were introduced in MATLAB. It seems that MATLAB itself also has problems
caused by evolution of the software and the desire to keep backwards compatibility! Because the &lt;code&gt;end&lt;/code&gt; method does not
know the context in which it is called, it has to guess what it is that the user wants, just like &lt;code&gt;size&lt;/code&gt; and &lt;code&gt;length&lt;/code&gt;
have to do. The decision to have all these functions make the same assumptions is sound, but if we would have thought
about tensor and color images before implementing these, they might have always looked only at the image dimensions and
never at the array dimensions.&lt;/p&gt;
&lt;h2&gt;Concatenating &lt;code&gt;dip_image&lt;/code&gt; and &lt;code&gt;dip_image_array&lt;/code&gt; objects&lt;/h2&gt;
&lt;p&gt;The last issue I have is with concatenation of images. Again, this was implemented before we even thought of the
possibility of using color images, and image arrays usually contained unrelated images. When concatenating an image
array, it is treated like one wishes to concatenate the images in the array. Therefore, &lt;code&gt;[A,B]&lt;/code&gt;, with &lt;code&gt;A&lt;/code&gt; an image
array, is equivalent to &lt;code&gt;[A{1},A{2},...,A{end},B]&lt;/code&gt;. This is very frustrating when you have two color images that you
wish to concatenate together. The workaround is, as usual with color images, to use &lt;code&gt;iterate&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;iterate&lt;/code&gt; repeats one operation on every image in an image array. This is often the only simple way of applying a filter
to an image. Bit by bit we are improving functions so that they work on tensor images. For example, &lt;code&gt;gaussf(A)&lt;/code&gt; now
works as expected on a color image. But many functions do not work yet, and many will never work (for example,
mathematical morphology on tensor images can not be defined properly, because there is no universally correct way to
decide which of a set of tensors is the largest). For these functions it is possible to use &lt;code&gt;iterate&lt;/code&gt; to apply them to
each of the components of a color image: &lt;code&gt;iterate('dilation',A,25,'rectangular')&lt;/code&gt;. Note that the result contains colors
not in the input image: this operation is not a dilation!&lt;/p&gt;
&lt;p&gt;&lt;code&gt;iterate&lt;/code&gt; is clever enough that, when it is called with multiple image arrays as input, it applies the function with
corresponding images from each of the arrays. Thus, to concatenate two color images, one can do &lt;code&gt;iterate('cat',1,A,B)&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;A better design&lt;/h2&gt;
&lt;p&gt;If we had thought about color images from the start, we would have created a &lt;code&gt;dip_image&lt;/code&gt; object that can hold a
grey-value, tensor or color image, but never unrelated images. An image array would be either a cell array with images
or a completely separate object. In that way it would be possible to have an array with one image, which now is
impossible. The &lt;code&gt;size&lt;/code&gt; and related functions would know whether the input is an image (whatever the type) or an image
array. Concatenation would be able to do different things on an image array and on a tensor image. However, the &lt;code&gt;end&lt;/code&gt;
operator would still be incomplete, only usable within brackets but not braces, and the limitation to the order of
brackets and braces would still stand. We would also have to introduce methods to return the size, length and number of
dimensions of the tensor.&lt;/p&gt;
&lt;p&gt;But it is too late for this type of change, I feel. I&amp;rsquo;m hoping this post will help people understand the design choices
made, and help them get around the limitations and oddities of the toolbox as it stands now.&lt;/p&gt;</content><category term="criticism"></category><category term="color"></category><category term="concatenating"></category><category term="design choices"></category><category term="dip_image object"></category><category term="dip_image_array object"></category><category term="DIPimage"></category><category term="end operator"></category><category term="evolution"></category><category term="imarsize"></category><category term="imsize"></category><category term="indexing"></category><category term="iterate"></category><category term="size method"></category><category term="tensor image"></category></entry><entry><title>Why do we keep using the word "pixel"?</title><link href="https://www.crisluengo.net/archives/51" rel="alternate"></link><published>2009-01-08T16:38:00-07:00</published><updated>2009-01-08T16:38:00-07:00</updated><author><name>Cris Luengo</name></author><id>tag:www.crisluengo.net,2009-01-08:/archives/51</id><summary type="html">&lt;p&gt;According to Wikipedia, the ultimate source of knowledge, the word &lt;a href="http://en.wikipedia.org/wiki/Pixel"&gt;pixel&lt;/a&gt; comes
from &amp;ldquo;picture element.&amp;rdquo; This means that a pixel is a part of a picture, and yet everybody I know keeps using that term
to refer to a part of an image. Because it is &amp;ldquo;image analysis&amp;rdquo; that we …&lt;/p&gt;</summary><content type="html">&lt;p&gt;According to Wikipedia, the ultimate source of knowledge, the word &lt;a href="http://en.wikipedia.org/wiki/Pixel"&gt;pixel&lt;/a&gt; comes
from &amp;ldquo;picture element.&amp;rdquo; This means that a pixel is a part of a picture, and yet everybody I know keeps using that term
to refer to a part of an image. Because it is &amp;ldquo;image analysis&amp;rdquo; that we do, right? Not &amp;ldquo;picture analysis&amp;rdquo;? Of course,
this is just an insignificant detail that I&amp;rsquo;m blowing way out of proportion. No, my real beef with the word pixel is
more complex.&lt;/p&gt;
&lt;p&gt;The word pixel seems to be used only in the context of 2D images. For 3D images we have a different word: voxel. So if I
have a 3D image, and take one 2D slice out of it by selecting a set of voxels, these voxels all of a sudden, magically,
become pixels! And what happens when you record a multi-spectral volumetric image? Or a volumetric time series? What do
you call the elements of a 4D, 5D or 10D image? Dean &lt;em&gt;et al.&lt;/em&gt; use the word imel (for image element) in
their &lt;a href="http://libics.sourceforge.net/"&gt;ICS file format&lt;/a&gt; specification (P. Dean &lt;em&gt;et al.&lt;/em&gt;, &amp;ldquo;Proposed standard for image
cytometry data files&amp;rdquo;, Cytometry 11(5):561-569,
1990, &lt;a href="http://dx.doi.org/10.1002/cyto.990110502"&gt;DOI:10.1002/cyto.990110502&lt;/a&gt;). Yes, it&amp;rsquo;s more general. Yes, it&amp;rsquo;s more
awkward. And yes, it still hides the fact that the images that we analyse are sampled and discretised representations of
some continuous reality. When we sample a function we obtain samples, not pixels. The data sets that we analyse are
collections of samples. A digital image is composed of samples, whether it be a 2D image, a 3D image or a 10D image.
Only after you paint a little rectangle on the screen with the color of your sample does it become a pixel.&lt;/p&gt;
&lt;p&gt;PS: I&amp;rsquo;m suggesting the word lixel for samples in a 1D signal. You heard it here first!&lt;/p&gt;</content><category term="criticism"></category><category term="ICS"></category><category term="multi-spectral"></category><category term="pixel"></category><category term="voxel"></category></entry></feed>