Imaging the difference of adjacent pixels using a digital micrograph (DM) script

The following digitalmicrograph function tries to create an image using the difference of an adjacent pixel in a substring of an image string. The first pixel is replaced with the average of the result of the difference of the substring created in this way.

eg. If the input image is 8 pixels wide and 1 line high, and the substring size is 4 - In_img = {8,9,2,4,9,8,7,5} Then the output image will be - Out_img = {average (8.9 , 2.4) = 5.75.9-8 = 1.2-9 = -7.4-2 = 2, average (9.8.7.5) = 7.25.8- 9 = -1 , 7-8 = -1.5-7 = -2}

enter image description here

When I run this script, the first pixel of the first line is correct, but the rest of the pixels are incorrect. When I set the loop limit to only one substring and one line, i.e. x = 1 and y = 1, then the script runs correctly.

Any ideas as to what might be happening or what might be wrong with the script?

test image here and result here .

    // Function to compute the standard deviation (sigma n-1) of an image, or
    // a set of values passed in as pixel values in an image. The
    // number of data points (n) the mean and the sum are also returned.
    // version:20080229
    // D. R. G. Mitchell, adminnospam@dmscripting.com (remove the nospam to make this email address work)
    // v1.0, February 2008
    void StandardDeviation(image arrayimg, number &stddev, number &n, number &mean, number &sum)
    {
        mean=mean(arrayimg)
        number xsize, ysize
        getsize(arrayimg,xsize, ysize)
        n=xsize*ysize
        sum=sum(arrayimg)
        image imgsquared=arrayimg*arrayimg
        number sumofvalssqrd=sum(imgsquared)
        stddev=sqrt(((n*sumofvalssqrd)-(sum*sum))/(n*(n-1)))
    }

image getVectorImage(image refImage, number rowsize)
{
    number fh, fv, fhx
    getsize(refImage, fh, fv)

    fhx=trunc(fh/rowsize)

    //result("ByteSize of refimage = "+refImage.ImageGetDataElementByteSize()+"\n")
    //create image to save std of each row of the ref image.  
    //The std values are saved as pixels of one row.  The row size is same as number of rows.
    //use fhx*rowsize for the new imagesize as fhx is truncated value.
    image retImage:=RealImage("",4,fhx*rowsize,fv)
    image workImage=slice1(refImage,rowsize+1,0,0,0,rowsize-1,1)

    number stddev,nopix,mean,sum

    for ( number y=0;y<fv;y++)
        {
        for (number x=0;x<fhx;x++) 
            {
                //result ("x,y="+x+","+y+"; fhx="+fhx+"; rowsize="+rowsize+"\n")
                workImage=slice1(refImage,x*rowsize+1,y,0,0,rowsize-1,1)-slice1(refImage,x*rowsize,y,0,0,rowsize-1,1)
                showimage(workImage)
                StandardDeviation(workImage,stddev,nopix,mean,sum )
                retImage[y,x*rowsize+1,y+1,x*rowsize+rowsize]=workImage
                retImage[y,x]=mean
                result("mean @ row "+y+" = "+mean+"\n")
            }
        }

    return retImage
}
showimage(getVectorImage(getfrontimage(),rowsize))

      

+1


source to share


2 answers


After your editing, I realized that you want to do something like this:

example

and that this should be done for each line of the image individually.

The following script does it. (Explanations below.)



image Modify( image in, number subsize )
{
    // Some checking
    number sx,sy
    in.GetSize(sx,sy)
    if ( 0 != sx%subsize )
        Throw( "The image width is not an integer multiplication of the subsize." )

    // Do the means...
    number nTile = sx/subsize
    image meanImg := RealImage( "Means", 4, nTile , sy )
    meanImg = 0
    for ( number i=0; i<subsize; i++ )
        meanImg += in.Slice2( i,0,0, 0,nTile,subsize, 1,sy,1 )

    meanImg *= 1/subsize

    // Do the shifted difference
    image dif := RealImage( "Diff", 4, sx-1, sy )
    dif = in.slice2( 1,0,0, 0,sx-1,1, 1,sy,1) - in.slice2( 0,0,0, 0,sx-1,1, 1,sy,1) 

    // Compile the result
    image out := in.ImageClone()
    out.SetName( in.getName() + "mod" )

    out.slice2( 1,0,0, 0,sx-1,1, 1,sy,1 ) = dif
    out.slice2( 0,0,0, 0,nTile,subsize, 1,sy,1 ) = meanImg

    return out
}


number sx = 8, sy = 4
image img := RealImage( "test", 4, 8, 4 )
img = icol*10 + trunc( Random()*10 )

img.ShowImage()
Modify(img,4).ShowImage()

      

Some explanations:

  • You want to do two different things on the image, so you need to be careful not to overwrite the pixel data that you will later use for calculations! Images are processed pixel by pixel, so if you first calculate the average and write it in the first pixel, the second pixel's estimate will be the difference of "9" and the average just stored (not the original "8",). Therefore, you need to split the computation and use "buffer" copies.

  • The command is slice2

    extremely convenient as it allows you to define a step when sampling. You can use it to refer to dark gray pixels directly.

  • Be aware of the difference between :=

    and =

    in image expressions. The first is the memory assignment:

    • A := B

      means A is now the same memory location as B. A is basically a different name for B.

    • A = B

      means A gets B values ​​(copied). A and B are two different memory locations and only values ​​are copied.

+1


source


I have some observations in your script:

  • Instead of a specific method to get the average / sum / stdev / n of an image, you can easily get those numbers from any image img

    using the following:

    means: number m = mean( img )

    sum: number s = sum( img )

    stdev: number sd = sqrt( variance( img ) )

    pixels: number n = sum( 0 * img + 1 )

  • if you want to get the difference of an image with an image "shifted by one", you do not need to iterate over the rows / columns, but you can use the command directly slice2()

    ; notation [] using icol and irow; or team offset()

    Personally, I prefer the team slice2()

    .

If I want a script that gives me the standard deviation of the difference of each line with its sequence, i.e. stdDev (row_ (y) - row_ (y + 1)) for all y <sizeY, my script would be:



Image img :=  GetFrontImage()
number sx,sy
img.GetSize(sx,sy)
number dy = 1

Image dif = img.Slice2(0,0,0, 0,sx,1, 1,sy-1,1 ) - img.Slice2(0,dy,0, 0,sx,1, 1,sy-1,1)
Image sDevs := RealImage( "Row stDev", 4, sy-1 )
for ( number y=0; y<sy-1; y++ )
    sDevs[y,0] = SQRT( Variance( dif.Slice1(0,y,0, 0,sx,1) ) )

sDevs.ShowImage()

      

Is this what you are trying to achieve? If not, edit your question to clarify.

+1


source







All Articles