Subscribe Bookmark RSS Feed

'Set Pixels' command isn't working as expected...?

ahutson22

Community Trekker

Joined:

Apr 10, 2015

I've cobbled together a script to correct an image, from grey-scale to just black and white.  The data looks right, but I would like to verify it visually by using the 'set pixels' command.  The resulting image appears to be a gradient, black on the left moving towards white to the right.

I'm new to JMP, please advise.

Thanks!

1 ACCEPTED SOLUTION

Accepted Solutions
Solution

Ah, I see what is happening. You are not doing anything wrong. We just need to add a wait() in between the data table creation and using the values from the data table that we are computing.

After the data table is created we are going through a loop, pulling out the values for :I, or in your script, :A. But both :I and :A are being computed with a formula. So we are attempting to pull the values out of the data table before the computations of the columns are completed. We need to wait long enough for the computations to complete before trying to use the values from our computed columns. In fact, if you run the code, look at the lower, left corner of the data table window as soon as it appears on the screen. You may see a message, "evaluating A", followed by another message, "evaluations done". You may not actually see the first message since it goes pretty quick. But we need to wait for the evaluations to be done before we can use the values.

To do that, just add this:

wait(3);

just after the data table creation statement and before the creation of the inten matrix. That should give the data table enough time to run the formulas. You may have to tweak the actual number (of seconds).

10 REPLIES
JohnPonte

Staff

Joined:

Jun 17, 2013

Here is some JSL that shows how to get an image, convert it to gray scale and then use 'set pixels' to replace the rgb image with the gray scale image.

img = newImage("$SAMPLE_IMAGES/tile.jpg");

{r, g, b} = img << get pixels("rgb");

i = .30*r + .59*g + .11*b;

img << set pixels("rgb", {i,i,i});

new window("Gray scale Image", img);

Notice that I am still setting the r, g, and b "channels", since the image is really a color image.

If this does not help, then post your JSL and I'll see if I can help you out.

Good Luck,

John Ponte

Craige_Hales

Staff

Joined:

Mar 21, 2013

Here's one way to do the black and white conversion.


img = newimage("$desktop/IcePlant.jpg");


{red,green,blue} = img<<getpixels("rgb");


sum = 0.2989*red + 0.5870*green + 0.1140*blue;


big=loc(sum>.5);


small=loc(sum<=.5);


sum[big]=1;


sum[small]=0;


bw = newimage("rgb",{sum,sum,sum});


newwindow("test", img, bw);


8624_blackandwhite.jpg

Craige
ahutson22

Community Trekker

Joined:

Apr 10, 2015

These are both very helpful.  I think I tried to skip over using r,g,b because the images were already in gray scale.

I've got a script that shows me the new black and white image, but what I had initially wanted to do, was pull the data from the image into a table, use a cut line command and assign either 1 or 0 for each pixel into a new column, and then put that column back into an image.... That's where my gradient was coming from and what was not working.

But thanks for the speedy responses!  I really appreciate it.

JohnPonte

Staff

Joined:

Jun 17, 2013

Here is some JSL that shows how to read in an image and create a data table from it. It also adds a new column for gray scale (intensity) and then creates a new image from the intensity column. You could modify the script to generate your bw column and then create the new image from that column in a similar way.

img = newImage("$SAMPLE_IMAGES/tile.jpg");

w = newWindow("image1", img);

{r, g, b} = img << getPixels("rgb");

numRows = nrow(r);

numCols = ncol(r);

dt = New Table("Pixel Data",

    newColumn("Y", set values(shape(repeat(1::numRows,numCols)`,numCols,numRows))),

    newColumn("X", set values(repeat(1::numCols, numRows))),

    newColumn("R", set values(r)),

    newColumn("G", set values(g)),

    newColumn("B", set values(b)),

    newColumn("I", formula(:r*0.3+:g*0.59+:b*0.11))

);


inten = J(numRows, numCols);

for each row (

    inten[:y, :x] = :I;

);

img2 = NewImage("rgb", {inten, inten, inten});

w2 = newWindow("image2", img2);



If you are new to JMP and using the image capabilities, you might find some of my example scripts useful. They are on the JMP File Exchange. In particular, you might want to look at  Image Example JSL andImageToDatatable JSL.


Craige_Hales

Staff

Joined:

Mar 21, 2013

I like that shape function, thanks for pointing it out.  I've been doing it the hard way.

Shape( [11 22, 33 44], 1, 4 );

[11 22 33 44]

Shape( [11 22, 33 44], 4, 1 );

[11, 22, 33, 44]

Shape( [11 22 33 44], 2, 2 );

[11 22, 33 44]

Shape( [11, 22, 33, 44], 2, 2 );

[11 22, 33 44]

Craige
ahutson22

Community Trekker

Joined:

Apr 10, 2015


I have been trying to use this to pull bw image data from the generated datatable, but all I am getting is black.  The data in the table appears to be correct, so I'm not sure where I've gone wrong.

melaniedrake

Staff

Joined:

May 30, 2014

I have the same problem, unless I put a wait statement after creating the new table. I think the script is proceeding with assigning values to inten from :A before the column formula has finished filling in :A.

I put a wait(0.5) there, and that fixed it for me. A wait(0) wasn't long enough. EG:

...

    newColumn("I", formula(:r*0.3+:g*0.59+:b*0.11)),

    New Column("A", formula(If(:I <= 0.5, 1, 0)))

);

wait(0.5); // let the column formula finish running

inten = J(numRows, numCols);

for each row (

...

Solution

Ah, I see what is happening. You are not doing anything wrong. We just need to add a wait() in between the data table creation and using the values from the data table that we are computing.

After the data table is created we are going through a loop, pulling out the values for :I, or in your script, :A. But both :I and :A are being computed with a formula. So we are attempting to pull the values out of the data table before the computations of the columns are completed. We need to wait long enough for the computations to complete before trying to use the values from our computed columns. In fact, if you run the code, look at the lower, left corner of the data table window as soon as it appears on the screen. You may see a message, "evaluating A", followed by another message, "evaluations done". You may not actually see the first message since it goes pretty quick. But we need to wait for the evaluations to be done before we can use the values.

To do that, just add this:

wait(3);

just after the data table creation statement and before the creation of the inten matrix. That should give the data table enough time to run the formulas. You may have to tweak the actual number (of seconds).

Craige_Hales

Staff

Joined:

Mar 21, 2013

The data table has a <<RunFormulas message that takes the guesswork out of how long to wait.  The formula evaluation happens in the background unless you use RunFormulas.

dt << RunFormulas;

Craige