together
together

Reputation: 75

How to split an image into subimages?

I would like to divide an image into a series of 256x256 pixels images.

The only coding method I thought of is drawing 256x256 ROI on the image and then create/crop a new image from the ROI area. (Please see the code below.)

Number size_x, size_y
image img 
img := GetFrontImage()
getsize( img, size_x, size_y )
showimage( img )

number x, y
For( y=0; y+256<size_y; y+=256 )
{
    For ( x=0; x+256<size_x; x+=256 )
    {
         ROI EMROI = NewROI()
         EMROI.ROISetRectangle( x, y, 256, 256 )
         img.ImageGetImageDisplay(0).ImageDisplayAddROI( EMROI )
         image cropped=img[]
         showimage(cropped)
    }
}

But there are two bugs: The script only draws ROIs in X-direction, not in Y-direction, and it always creates the new image only from the first ROI. Is there a better way to divide DM images? Or how should I change my code to achieve it?

Upvotes: 0

Views: 1242

Answers (2)

BmyGuest
BmyGuest

Reputation: 2949

This is the answer regarding what is wrong with your script:

You use the command ROISetRectangle incorrectly.

The parameters of the command are not X,Y,height,width but the same top / left / bottom / right notation I have descriped in the other answer for the [t,l,b,r] notation.

Your script would actually work if you replace the one line by:

EMROI.ROISetRectangle( y, x, y + 256, x + 256 )

There is no need to use "visual" ROIs for what you want. (see other answer)

Instead of [] to use specify a visual ROI, you can use [t,l,b,r] to specify the region directly. Note, that you could also add the ROI you added by a simple command:

img.SetSelection( t, l, b, r )

with the same meaning of t,l,b,r.

The ImageDisplay and ROI command you use are the "lower level" commands whihc can do more things. You use them correclty, but you don't always need to use them, if you can get things done with simpler commands.

It is usually a better syntax to define the variables used in a for loop within the for-loop and not outside of it. This will make them local and prevents unwanted potential bugs.

Instead of

number x
for( x=0; x<10; x++ )
{
}

Use

for( number x=0; x<10; x++ )
{
}

Careful when copying images. the = operator will only copy the values. You can use the := operator to address any data or sub-data (no addtional memory) and then use the command ImageClone() to create an exact copy, including meta-data such as calibrations or tags.

So in you script you may want to use

image cropped := ImageClone( img[] )

Upvotes: 0

BmyGuest
BmyGuest

Reputation: 2949

This post is answering your question regarding the thing you want to achieve (the splitting of and image).

Yes, there is a better way to do this. You can address any "subsection" of a data directly by using the [ t, l, b, r ] notation in which you use the 4 numbers to specify the region. t top, l left, b bottom, r, right as in:

Corodinates

Or, alternativly, you can use the slice command to address subsections using a starting point, and then for each output dimension a triplet specifying direction, length, stride as in:

Slice command


The script you want would likely be a variant of the following

// Create TestImage
number sx = 1024
number sy = 1024
image img := RealImage( "Test", 4, sx, sy )
img = itheta * sin( (iradius+icol)/iwidth * 50 * pi() )
img.ShowImage()

// Split up into N x M images
// Optional: Perform check for integer-values using mod-division (% operator)
number n = 2
number m = 4
number notExact = ( sx % n != 0 ) || ( sy % m != 0 ) 
if ( notExact ) 
    if ( !OKCancelDialog( "The image split is not an integer division. Continue?" ) ) 
        exit(0)

number bx = sx/n
number by = sy/m

for( number row = 0; row < m; row++ )
    for( number col= 0; col< n; col++ )
        {
            // We want the sub-rect. We could use [t,l,b,r] notation, but I prefer slice2()
            number x0 = col * bx
            number y0 = row * by
            image sub := img.Slice2( x0,y0,0, 0,bx,1, 1,by,1 ).ImageClone() // CLONE the referenced data to create a copy
            sub.SetName( img.GetName() + "__"+col+"_"+row )
            sub.ShowImage()
        }

If something remains unclear, please ask!

Upvotes: 0

Related Questions