linear transform

classic Classic list List threaded Threaded
10 messages Options
Reply | Threaded
Open this post in threaded view
|

linear transform

foxtango
Hi everybody,

I have a number of 16bit images. The highest gray value is 65535 in all of
them. The lowest gray value varies between 20000 and 40000. How can I
transform all images in a linear fashion leaving the highest gray value at
65535 and set the lowest to 30000?

With Enhance Contrast I can stretch the distribution in such a manner that
the lowest gray value is zero. But I want to stretch the distribution in
some images and condens it in others.

Thank you, Thomas

--
ImageJ mailing list: http://imagej.nih.gov/ij/list.html
Thomas
Reply | Threaded
Open this post in threaded view
|

Re: linear transform

Robert Lockwood
Thomas, this is a math problem in four steps,
1. Translate the values from the current minimum of 20000 to a minimum of
zero by subtracting 20000 from the pixel value.
2. Calculate a new value between 0 and 1 by dividing it by the existing
range (65535 - 20000)
3. Multiply that value by the desired range (65535 - 30000)
4. Finally translate the value by adding the new minimum (and rounding it)
newValue =      round( ((oldValue - oldMin)/oldRange)*newRange + newMin)

I tested this for these values and results
20,000, 30,000, 40,000, and 65,535
30,000, 37,787, 45,574, and 65,535

To increase the speed, newRange/oldRange can be moved outside the loop as
it is a constant.
If you have a few times more pixels than 65,535 - 20,000 (45,535 + 1) and
many files I suggest pre-calculating each value into an array as a lookup
table. if speed matters.

HTH
Nate


On Fri, Jun 12, 2020 at 2:32 PM Thomas Fischer <[hidden email]> wrote:

> Hi everybody,
>
> I have a number of 16bit images. The highest gray value is 65535 in all of
> them. The lowest gray value varies between 20000 and 40000. How can I
> transform all images in a linear fashion leaving the highest gray value at
> 65535 and set the lowest to 30000?
>
> With Enhance Contrast I can stretch the distribution in such a manner that
> the lowest gray value is zero. But I want to stretch the distribution in
> some images and condens it in others.
>
> Thank you, Thomas
>
> --
> ImageJ mailing list: http://imagej.nih.gov/ij/list.html
>

--
ImageJ mailing list: http://imagej.nih.gov/ij/list.html
Reply | Threaded
Open this post in threaded view
|

Re: linear transform

Robert Smith
Robert, excellent and best approach- with one recommendation, instead of simply subtracting 20000 from everything use the Math>Macro>(v=v*20000) which would subtract  that value from all pixels and would be much faster than a array while not changing the range of any of them.  Just a suggestion.
Bob


________________________________
From: Robert Lockwood <[hidden email]>
Sent: Friday, June 12, 2020 7:49 PM
To: [hidden email] <[hidden email]>
Subject: Re: linear transform

Thomas, this is a math problem in four steps,
1. Translate the values from the current minimum of 20000 to a minimum of
zero by subtracting 20000 from the pixel value.
2. Calculate a new value between 0 and 1 by dividing it by the existing
range (65535 - 20000)
3. Multiply that value by the desired range (65535 - 30000)
4. Finally translate the value by adding the new minimum (and rounding it)
newValue =      round( ((oldValue - oldMin)/oldRange)*newRange + newMin)(

I tested this for these values and results
20,000, 30,000, 40,000, and 65,535
30,000, 37,787, 45,574, and 65,535

To increase the speed, newRange/oldRange can be moved outside the loop as
it is a constant.
If you have a few times more pixels than 65,535 - 20,000 (45,535 + 1) and
many files I suggest pre-calculating each value into an array as a lookup
table. if speed matters.

HTH
Nate


On Fri, Jun 12, 2020 at 2:32 PM Thomas Fischer <[hidden email]> wrote:

> Hi everybody,
>
> I have a number of 16bit images. The highest gray value is 65535 in all of
> them. The lowest gray value varies between 20000 and 40000. How can I
> transform all images in a linear fashion leaving the highest gray value at
> 65535 and set the lowest to 30000?
>
> With Enhance Contrast I can stretch the distribution in such a manner that
> the lowest gray value is zero. But I want to stretch the distribution in
> some images and condens it in others.
>
> Thank you, Thomas
>
> --
> ImageJ mailing list: https://eur05.safelinks.protection.outlook.com/?url=http%3A%2F%2Fimagej.nih.gov%2Fij%2Flist.html&amp;data=02%7C01%7C%7Ce9ac4880ab2b428012c508d80f2bc62d%7C84df9e7fe9f640afb435aaaaaaaaaaaa%7C1%7C0%7C637276027973125539&amp;sdata=XrP9B1AVEwWhJEeX2GJk9V07blnxdxdD92fv4FSbG2Y%3D&amp;reserved=0
>

--
ImageJ mailing list: https://eur05.safelinks.protection.outlook.com/?url=http%3A%2F%2Fimagej.nih.gov%2Fij%2Flist.html&amp;data=02%7C01%7C%7Ce9ac4880ab2b428012c508d80f2bc62d%7C84df9e7fe9f640afb435aaaaaaaaaaaa%7C1%7C0%7C637276027973135535&amp;sdata=P8JR93MtOyspCWEIZUpuo0%2BX5tIhhVCMldq4jLiG8kM%3D&amp;reserved=0

--
ImageJ mailing list: http://imagej.nih.gov/ij/list.html
Reply | Threaded
Open this post in threaded view
|

Re: linear transform

foxtango
Thanks to both Roberts,

I confess that I use imagej in a very simple way. Unless I find a code on
the internet I embed the result of the macro recorder in a shell script
which replaces the variable parameters. Since the present task lends itself
to batch programming I have two questions.

1) I know how to extract the list of histogram values and from that I can
extract the lowest bin which is different in every image. But there must be
a possibility to get the MIN that is shown on the histogram window
directly, without the detour via the whole histogram.

2) Could you point out how the core of the math operations looks like. I do
know the input and output periphery.

Thanks again, Thomas


Am Sa., 13. Juni 2020 um 02:43 Uhr schrieb Robert Smith <[hidden email]
>:

> Robert, excellent and best approach- with one recommendation, instead of
> simply subtracting 20000 from everything use the Math>Macro>(v=v*20000)
> which would subtract  that value from all pixels and would be much faster
> than a array while not changing the range of any of them.  Just a
> suggestion.
> Bob
>
>
> ________________________________
> From: Robert Lockwood <[hidden email]>
> Sent: Friday, June 12, 2020 7:49 PM
> To: [hidden email] <[hidden email]>
> Subject: Re: linear transform
>
> Thomas, this is a math problem in four steps,
> 1. Translate the values from the current minimum of 20000 to a minimum of
> zero by subtracting 20000 from the pixel value.
> 2. Calculate a new value between 0 and 1 by dividing it by the existing
> range (65535 - 20000)
> 3. Multiply that value by the desired range (65535 - 30000)
> 4. Finally translate the value by adding the new minimum (and rounding it)
> newValue =      round( ((oldValue - oldMin)/oldRange)*newRange + newMin)(
>
> I tested this for these values and results
> 20,000, 30,000, 40,000, and 65,535
> 30,000, 37,787, 45,574, and 65,535
>
> To increase the speed, newRange/oldRange can be moved outside the loop as
> it is a constant.
> If you have a few times more pixels than 65,535 - 20,000 (45,535 + 1) and
> many files I suggest pre-calculating each value into an array as a lookup
> table. if speed matters.
>
> HTH
> Nate
>
>
> On Fri, Jun 12, 2020 at 2:32 PM Thomas Fischer <[hidden email]>
> wrote:
>
> > Hi everybody,
> >
> > I have a number of 16bit images. The highest gray value is 65535 in all
> of
> > them. The lowest gray value varies between 20000 and 40000. How can I
> > transform all images in a linear fashion leaving the highest gray value
> at
> > 65535 and set the lowest to 30000?
> >
> > With Enhance Contrast I can stretch the distribution in such a manner
> that
> > the lowest gray value is zero. But I want to stretch the distribution in
> > some images and condens it in others.
> >
> > Thank you, Thomas
> >
> > --
> > ImageJ mailing list:
> https://eur05.safelinks.protection.outlook.com/?url=http%3A%2F%2Fimagej.nih.gov%2Fij%2Flist.html&amp;data=02%7C01%7C%7Ce9ac4880ab2b428012c508d80f2bc62d%7C84df9e7fe9f640afb435aaaaaaaaaaaa%7C1%7C0%7C637276027973125539&amp;sdata=XrP9B1AVEwWhJEeX2GJk9V07blnxdxdD92fv4FSbG2Y%3D&amp;reserved=0
> >
>
> --
> ImageJ mailing list:
> https://eur05.safelinks.protection.outlook.com/?url=http%3A%2F%2Fimagej.nih.gov%2Fij%2Flist.html&amp;data=02%7C01%7C%7Ce9ac4880ab2b428012c508d80f2bc62d%7C84df9e7fe9f640afb435aaaaaaaaaaaa%7C1%7C0%7C637276027973135535&amp;sdata=P8JR93MtOyspCWEIZUpuo0%2BX5tIhhVCMldq4jLiG8kM%3D&amp;reserved=0
>
> --
> ImageJ mailing list: http://imagej.nih.gov/ij/list.html
>

--
ImageJ mailing list: http://imagej.nih.gov/ij/list.html
Thomas
Reply | Threaded
Open this post in threaded view
|

Re: linear transform

CARL Philippe (LBP)
In reply to this post by Robert Smith
Dear Bob,
I'm really not an expert of these pixels operations but like Nelson Mandela said: "I never lose. I either win or learn".
Thus if what I will be writing below is wrong, I will then be able to learn from my errors!
But in order to subtract 20000 from everything shouldn't you rather use the Math>Macro>(v=v-20000) [instead of the Math>Macro>(v=v*20000) your wrote ?]
Also wouldn't it even be simpler to just use the Process>Math>Substract...>20000 ?
My best regards,
Philippe

Philippe CARL
Laboratoire de Bioimagerie et Pathologies
UMR 7021 CNRS - Université de Strasbourg
Faculté de Pharmacie
74 route du Rhin
67401 ILLKIRCH
Tel : +33(0)3 68 85 42 89

----- Mail original -----
De: "Robert Smith" <[hidden email]>
À: "imagej" <[hidden email]>
Envoyé: Samedi 13 Juin 2020 02:42:06
Objet: Re: linear transform

Robert, excellent and best approach- with one recommendation, instead of simply subtracting 20000 from everything use the Math>Macro>(v=v*20000) which would subtract  that value from all pixels and would be much faster than a array while not changing the range of any of them.  Just a suggestion.
Bob


________________________________
From: Robert Lockwood <[hidden email]>
Sent: Friday, June 12, 2020 7:49 PM
To: [hidden email] <[hidden email]>
Subject: Re: linear transform

Thomas, this is a math problem in four steps,
1. Translate the values from the current minimum of 20000 to a minimum of
zero by subtracting 20000 from the pixel value.
2. Calculate a new value between 0 and 1 by dividing it by the existing
range (65535 - 20000)
3. Multiply that value by the desired range (65535 - 30000)
4. Finally translate the value by adding the new minimum (and rounding it)
newValue =      round( ((oldValue - oldMin)/oldRange)*newRange + newMin)(

I tested this for these values and results
20,000, 30,000, 40,000, and 65,535
30,000, 37,787, 45,574, and 65,535

To increase the speed, newRange/oldRange can be moved outside the loop as
it is a constant.
If you have a few times more pixels than 65,535 - 20,000 (45,535 + 1) and
many files I suggest pre-calculating each value into an array as a lookup
table. if speed matters.

HTH
Nate


On Fri, Jun 12, 2020 at 2:32 PM Thomas Fischer <[hidden email]> wrote:

> Hi everybody,
>
> I have a number of 16bit images. The highest gray value is 65535 in all of
> them. The lowest gray value varies between 20000 and 40000. How can I
> transform all images in a linear fashion leaving the highest gray value at
> 65535 and set the lowest to 30000?
>
> With Enhance Contrast I can stretch the distribution in such a manner that
> the lowest gray value is zero. But I want to stretch the distribution in
> some images and condens it in others.
>
> Thank you, Thomas
>
> --
> ImageJ mailing list: https://eur05.safelinks.protection.outlook.com/?url=http%3A%2F%2Fimagej.nih.gov%2Fij%2Flist.html&amp;data=02%7C01%7C%7Ce9ac4880ab2b428012c508d80f2bc62d%7C84df9e7fe9f640afb435aaaaaaaaaaaa%7C1%7C0%7C637276027973125539&amp;sdata=XrP9B1AVEwWhJEeX2GJk9V07blnxdxdD92fv4FSbG2Y%3D&amp;reserved=0
>

--
ImageJ mailing list: https://eur05.safelinks.protection.outlook.com/?url=http%3A%2F%2Fimagej.nih.gov%2Fij%2Flist.html&amp;data=02%7C01%7C%7Ce9ac4880ab2b428012c508d80f2bc62d%7C84df9e7fe9f640afb435aaaaaaaaaaaa%7C1%7C0%7C637276027973135535&amp;sdata=P8JR93MtOyspCWEIZUpuo0%2BX5tIhhVCMldq4jLiG8kM%3D&amp;reserved=0

--
ImageJ mailing list: http://imagej.nih.gov/ij/list.html

--
ImageJ mailing list: http://imagej.nih.gov/ij/list.html
Reply | Threaded
Open this post in threaded view
|

Re: linear transform

Robert Smith
You are absolutely correct young man, I didn't catch the error untill after I hit the send key.  Finger dyslexia in an old man. My apologies, and however no you would only subtract the 20000, thereby lowering
the overall level of the image while maintaining the orginial range of intensity.
Again, I apologize.
Bob 😊

________________________________
From: ImageJ Interest Group <[hidden email]> on behalf of CARL Philippe (LBP) <[hidden email]>
Sent: Saturday, June 13, 2020 9:36 AM
To: [hidden email] <[hidden email]>
Subject: Re: linear transform

Dear Bob,
I'm really not an expert of these pixels operations but like Nelson Mandela said: "I never lose. I either win or learn".
Thus if what I will be writing below is wrong, I will then be able to learn from my errors!
But in order to subtract 20000 from everything shouldn't you rather use the Math>Macro>(v=v-20000) [instead of the Math>Macro>(v=v*20000) your wrote ?]
Also wouldn't it even be simpler to just use the Process>Math>Substract...>20000 ?
My best regards,
Philippe

Philippe CARL
Laboratoire de Bioimagerie et Pathologies
UMR 7021 CNRS - Université de Strasbourg
Faculté de Pharmacie
74 route du Rhin
67401 ILLKIRCH
Tel : +33(0)3 68 85 42 89

----- Mail original -----
De: "Robert Smith" <[hidden email]>
À: "imagej" <[hidden email]>
Envoyé: Samedi 13 Juin 2020 02:42:06
Objet: Re: linear transform

Robert, excellent and best approach- with one recommendation, instead of simply subtracting 20000 from everything use the Math>Macro>(v=v*20000) which would subtract  that value from all pixels and would be much faster than a array while not changing the range of any of them.  Just a suggestion.
Bob


________________________________
From: Robert Lockwood <[hidden email]>
Sent: Friday, June 12, 2020 7:49 PM
To: [hidden email] <[hidden email]>
Subject: Re: linear transform

Thomas, this is a math problem in four steps,
1. Translate the values from the current minimum of 20000 to a minimum of
zero by subtracting 20000 from the pixel value.
2. Calculate a new value between 0 and 1 by dividing it by the existing
range (65535 - 20000)
3. Multiply that value by the desired range (65535 - 30000)
4. Finally translate the value by adding the new minimum (and rounding it)
newValue =      round( ((oldValue - oldMin)/oldRange)*newRange + newMin)(

I tested this for these values and results
20,000, 30,000, 40,000, and 65,535
30,000, 37,787, 45,574, and 65,535

To increase the speed, newRange/oldRange can be moved outside the loop as
it is a constant.
If you have a few times more pixels than 65,535 - 20,000 (45,535 + 1) and
many files I suggest pre-calculating each value into an array as a lookup
table. if speed matters.

HTH
Nate


On Fri, Jun 12, 2020 at 2:32 PM Thomas Fischer <[hidden email]> wrote:

> Hi everybody,
>
> I have a number of 16bit images. The highest gray value is 65535 in all of
> them. The lowest gray value varies between 20000 and 40000. How can I
> transform all images in a linear fashion leaving the highest gray value at
> 65535 and set the lowest to 30000?
>
> With Enhance Contrast I can stretch the distribution in such a manner that
> the lowest gray value is zero. But I want to stretch the distribution in
> some images and condens it in others.
>
> Thank you, Thomas
>
> --
> ImageJ mailing list: https://eur01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fimagej.nih.gov%2Fij%2Flist.html&amp;data=02%7C01%7C%7Ce8a57509af6943a4d14808d80f9ee006%7C84df9e7fe9f640afb435aaaaaaaaaaaa%7C1%7C0%7C637276522322408782&amp;sdata=r%2FwhGAIrnLekJKjNmRex4q6u4MbiSzxNF3cBwGJ3d54%3D&amp;reserved=0
>

--
ImageJ mailing list: https://eur01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fimagej.nih.gov%2Fij%2Flist.html&amp;data=02%7C01%7C%7Ce8a57509af6943a4d14808d80f9ee006%7C84df9e7fe9f640afb435aaaaaaaaaaaa%7C1%7C0%7C637276522322418776&amp;sdata=3TWpGU7jGzY2UCW2Rjz0Ut29kCwlI4Q6N%2Few2ZVXhmM%3D&amp;reserved=0

--
ImageJ mailing list: https://eur01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fimagej.nih.gov%2Fij%2Flist.html&amp;data=02%7C01%7C%7Ce8a57509af6943a4d14808d80f9ee006%7C84df9e7fe9f640afb435aaaaaaaaaaaa%7C1%7C0%7C637276522322418776&amp;sdata=3TWpGU7jGzY2UCW2Rjz0Ut29kCwlI4Q6N%2Few2ZVXhmM%3D&amp;reserved=0

--
ImageJ mailing list: https://eur01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fimagej.nih.gov%2Fij%2Flist.html&amp;data=02%7C01%7C%7Ce8a57509af6943a4d14808d80f9ee006%7C84df9e7fe9f640afb435aaaaaaaaaaaa%7C1%7C0%7C637276522322418776&amp;sdata=3TWpGU7jGzY2UCW2Rjz0Ut29kCwlI4Q6N%2Few2ZVXhmM%3D&amp;reserved=0

--
ImageJ mailing list: http://imagej.nih.gov/ij/list.html
Reply | Threaded
Open this post in threaded view
|

Re: linear transform

Herbie
In reply to this post by foxtango
Good day Thomas,

the following macro code applies the desired linear transformation to
all values of a 16bit image. (Test image appended.)

// imagej-macro "linTrans" (Herbie G., 13. June 2020)
requires("1.53b");
run("Revert");
w = getWidth;
h = getHeight;
img = getImageID;
getRawStatistics( n, mn, currMin );
max = 65635;
min = 30000; // desired minimum
b = ( max - min );
b /= ( max - currMin );
a = max * ( 1 - b );
run("Plot Profile"); // ????
selectImage( img );
for ( j=0; j<h; j++ ) {
    for ( i=0; i<w; i++ ) {
       setPixel( i, j, linTrans( a, b, getPixel( i, j ) ) );
    }
}
run("Plot Profile"); // ????
exit();
function linTrans( x, y, z ) { return round( x + y * z ); }
// imagej-macro "linTrans" (Herbie G., 13. June 2020)

Paste the above macro code to an empty macro window (Plugins >> New >>
Macro), open the test image, then run the macro.

With the test image you get two profiles along the image diagonal, one
taken before the transformation, the other after the transformation.

If your image doesn't have a selection, you must comment or eliminate
the code lines denoted with "????".

Please note that transforming an image per macro code is slow.
You need a plugin to perform fast pixel-wise operations.

Regards

Herbie

::::::::::::::::::::::::::::::::::::::::::::
Am 12.06.20 um 22:58 schrieb Thomas Fischer:

> Hi everybody,
>
> I have a number of 16bit images. The highest gray value is 65535 in all of
> them. The lowest gray value varies between 20000 and 40000. How can I
> transform all images in a linear fashion leaving the highest gray value at
> 65535 and set the lowest to 30000?
>
> With Enhance Contrast I can stretch the distribution in such a manner that
> the lowest gray value is zero. But I want to stretch the distribution in
> some images and condens it in others.
>
> Thank you, Thomas
--
ImageJ mailing list: http://imagej.nih.gov/ij/list.html

20019.tif (11K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: linear transform

Herbie
In reply to this post by foxtango
Sorry Thomas,

there was a little typo in the code!

Please correct the value according to:
max = 65535;

Attached please find an additional test image.

Regards

Herbie

::::::::::::::::::::::::::::::::::::::::::::

Good day Thomas,

the following macro code applies the desired linear transformation to
all values of a 16bit image. (Test image appended.)

// imagej-macro "linTrans" (Herbie G., 13. June 2020)
requires("1.53b");
run("Revert");
w = getWidth;
h = getHeight;
img = getImageID;
getRawStatistics( n, mn, currMin );
max = 65635;
min = 30000; // desired minimum
b = ( max - min );
b /= ( max - currMin );
a = max * ( 1 - b );
run("Plot Profile"); // ????
selectImage( img );
for ( j=0; j<h; j++ ) {
     for ( i=0; i<w; i++ ) {
        setPixel( i, j, linTrans( a, b, getPixel( i, j ) ) );
     }
}
run("Plot Profile"); // ????
exit();
function linTrans( x, y, z ) { return round( x + y * z ); }
// imagej-macro "linTrans" (Herbie G., 13. June 2020)

Paste the above macro code to an empty macro window (Plugins >> New >>
Macro), open the test image, then run the macro.

With the test image you get two profiles along the image diagonal, one
taken before the transformation, the other after the transformation.

If your image doesn't have a selection, you must comment or eliminate
the code lines denoted with "????".

Please note that transforming an image per macro code is slow.
You need a plugin to perform fast pixel-wise operations.

Regards

Herbie

::::::::::::::::::::::::::::::::::::::::::::
Am 12.06.20 um 22:58 schrieb Thomas Fischer:

> Hi everybody,
>
> I have a number of 16bit images. The highest gray value is 65535 in all of
> them. The lowest gray value varies between 20000 and 40000. How can I
> transform all images in a linear fashion leaving the highest gray value at
> 65535 and set the lowest to 30000?
>
> With Enhance Contrast I can stretch the distribution in such a manner that
> the lowest gray value is zero. But I want to stretch the distribution in
> some images and condens it in others.
>
> Thank you, Thomas

--
ImageJ mailing list: http://imagej.nih.gov/ij/list.html

20019.tif (11K) Download Attachment
39931.tif (14K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: linear transform

Herbie
In reply to this post by foxtango
Good day Thomas,

the following code is about 10 times faster than the previous:

// imagej-macro "linTrans" (Herbie G., 14. June 2020)
requires("1.53b");
run("Revert");
setOption("ScaleConversions", false);
w = getWidth;
h = getHeight;
img = getImageID;
getRawStatistics( n, mn, currMin );
max = 65535;
min = 30000; // desired minimum
b = ( max - min );
b /= ( max - currMin );
a = max * ( 1 - b );
run("Plot Profile"); // ????
selectImage( img );
run( "32-bit" );
run("Multiply...", "value=&b");
run("Add...", "value=&a");
run( "16-bit");
run("Plot Profile"); // ????
exit();
// imagej-macro "linTrans" (Herbie G., 14. June 2020)

A plugin will be even faster...

Regards

Herbie

::::::::::::::::::::::::::::::::::::::::::::
Sorry Thomas,

there was a little typo in the code!

Please correct the value according to:
max = 65535;

Attached please find an additional test image.

Regards

Herbie

::::::::::::::::::::::::::::::::::::::::::::

Good day Thomas,

the following macro code applies the desired linear transformation to
all values of a 16bit image. (Test image appended.)

// imagej-macro "linTrans" (Herbie G., 13. June 2020)
requires("1.53b");
run("Revert");
w = getWidth;
h = getHeight;
img = getImageID;
getRawStatistics( n, mn, currMin );
max = 65635;
min = 30000; // desired minimum
b = ( max - min );
b /= ( max - currMin );
a = max * ( 1 - b );
run("Plot Profile"); // ????
selectImage( img );
for ( j=0; j<h; j++ ) {
      for ( i=0; i<w; i++ ) {
         setPixel( i, j, linTrans( a, b, getPixel( i, j ) ) );
      }
}
run("Plot Profile"); // ????
exit();
function linTrans( x, y, z ) { return round( x + y * z ); }
// imagej-macro "linTrans" (Herbie G., 13. June 2020)

Paste the above macro code to an empty macro window (Plugins >> New >>
Macro), open the test image, then run the macro.

With the test image you get two profiles along the image diagonal, one
taken before the transformation, the other after the transformation.

If your image doesn't have a selection, you must comment or eliminate
the code lines denoted with "????".

Please note that transforming an image per macro code is slow.
You need a plugin to perform fast pixel-wise operations.

Regards

Herbie

::::::::::::::::::::::::::::::::::::::::::::
Am 12.06.20 um 22:58 schrieb Thomas Fischer:

> Hi everybody,
>
> I have a number of 16bit images. The highest gray value is 65535 in all of
> them. The lowest gray value varies between 20000 and 40000. How can I
> transform all images in a linear fashion leaving the highest gray value at
> 65535 and set the lowest to 30000?
>
> With Enhance Contrast I can stretch the distribution in such a manner that
> the lowest gray value is zero. But I want to stretch the distribution in
> some images and condens it in others.
>
> Thank you, Thomas


--
ImageJ mailing list: http://imagej.nih.gov/ij/list.html

--
ImageJ mailing list: http://imagej.nih.gov/ij/list.html
Reply | Threaded
Open this post in threaded view
|

Re: linear transform

Herbie
In reply to this post by foxtango
For those of you interested in this thread,

here is the conversion-macro for batch-processing:

// imagej-macro "linTrans_Dir" (Herbie G., 15. June 2020)
requires( "1.53b" );
srce = getDirectory( "Choose the Source Directory" )
dest = getDirectory( "Choose the Destination Directory" );
min = 30000; // desired minimum
max = 65535;
d = max - min;
setOption( "ScaleConversions", false );
list = getFileList( srce );
setBatchMode( true );
for ( i=0; i<list.length; i++ ) {
    open( srce + list[i] );
    linTrans_fast( d, max );
    save( dest + list[i] );
    close();
}
setBatchMode( false );
exit();
function linTrans_fast( b, mx ) {
    getRawStatistics( n, mn, currMin );
    b /= ( mx - currMin );
    a = mx * ( 1 - b );
    run( "32-bit" );
    run( "Multiply...", "value=&b" );
    run( "Add...", "value=&a" );
    run( "16-bit" );
}
// imagej-macro "linTrans_Dir" (Herbie G., 15. June 2020)

Regards

Herbie

::::::::::::::::::::::::::::::::::::::::::::

Good day Thomas,

the following code is about 10 times faster than the previous:

// imagej-macro "linTrans" (Herbie G., 14. June 2020)
requires("1.53b");
run("Revert");
setOption("ScaleConversions", false);
w = getWidth;
h = getHeight;
img = getImageID;
getRawStatistics( n, mn, currMin );
max = 65535;
min = 30000; // desired minimum
b = ( max - min );
b /= ( max - currMin );
a = max * ( 1 - b );
run("Plot Profile"); // ????
selectImage( img );
run( "32-bit" );
run("Multiply...", "value=&b");
run("Add...", "value=&a");
run( "16-bit");
run("Plot Profile"); // ????
exit();
// imagej-macro "linTrans" (Herbie G., 14. June 2020)

A plugin will be even faster...

Regards

Herbie

::::::::::::::::::::::::::::::::::::::::::::
Sorry Thomas,

there was a little typo in the code!

Please correct the value according to:
max = 65535;

Attached please find an additional test image.

Regards

Herbie

::::::::::::::::::::::::::::::::::::::::::::

Good day Thomas,

the following macro code applies the desired linear transformation to
all values of a 16bit image. (Test image appended.)

// imagej-macro "linTrans" (Herbie G., 13. June 2020)
requires("1.53b");
run("Revert");
w = getWidth;
h = getHeight;
img = getImageID;
getRawStatistics( n, mn, currMin );
max = 65635;
min = 30000; // desired minimum
b = ( max - min );
b /= ( max - currMin );
a = max * ( 1 - b );
run("Plot Profile"); // ????
selectImage( img );
for ( j=0; j<h; j++ ) {
      for ( i=0; i<w; i++ ) {
         setPixel( i, j, linTrans( a, b, getPixel( i, j ) ) );
      }
}
run("Plot Profile"); // ????
exit();
function linTrans( x, y, z ) { return round( x + y * z ); }
// imagej-macro "linTrans" (Herbie G., 13. June 2020)

Paste the above macro code to an empty macro window (Plugins >> New >>
Macro), open the test image, then run the macro.

With the test image you get two profiles along the image diagonal, one
taken before the transformation, the other after the transformation.

If your image doesn't have a selection, you must comment or eliminate
the code lines denoted with "????".

Please note that transforming an image per macro code is slow.
You need a plugin to perform fast pixel-wise operations.

Regards

Herbie

::::::::::::::::::::::::::::::::::::::::::::
Am 12.06.20 um 22:58 schrieb Thomas Fischer:

> Hi everybody,
>
> I have a number of 16bit images. The highest gray value is 65535 in all of
> them. The lowest gray value varies between 20000 and 40000. How can I
> transform all images in a linear fashion leaving the highest gray value at
> 65535 and set the lowest to 30000?
>
> With Enhance Contrast I can stretch the distribution in such a manner that
> the lowest gray value is zero. But I want to stretch the distribution in
> some images and condens it in others.
>
> Thank you, Thomas


--
ImageJ mailing list: http://imagej.nih.gov/ij/list.html

--
ImageJ mailing list: http://imagej.nih.gov/ij/list.html

--
ImageJ mailing list: http://imagej.nih.gov/ij/list.html