Reputation: 75
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
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 commandImageClone()
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
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:
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:
// 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