With several ROIs in an image, how can I send the ROI to the back - dm-script

When I have several ROIs in an image, they can overlap and sometimes the smaller one gets lost behind the bigger one. However, one of the is on "top" and the other is "below." I have the ID of the ROI, but I am missing the command ROI_ID.ROISendToBack() or similar.
Any trick available?
Thanks!

The order of ROIs on a display can not be the property of an individual ROI, but it is a property of the thing 'containing' the ROIs. That's why you search for the command at the wrong place. It is not a command of the ROI object, but of the ImageDisplay object.
Each ImageDisplay contains a "list" of its ROIs and you want to change the order in that list.
The commands for specifying the "order" of ROIs on an ImageDisplay are
There is no command to "move" a ROI, but you can simple remove and re-add it.
image img := RealImage( "Dummy",4, 350, 350)
img = iradius
img.ShowImage()
imageDisplay disp = img.ImageGetImageDisplay(0)
ROI roi1 = NewROI()
roi1.ROISetRectangle( 100, 100, 200, 200 )
roi1.ROISetVolatile(0)
roi1.ROISetColor(1,0,0)
roi1.ROISetDrawFilled(1)
roi1.ROISetFillProperties(0.2,0.1,0,0)
ROI roi2 = NewROI()
roi2.ROISetRectangle( 125, 125, 225, 225 )
roi2.ROISetVolatile(0)
roi2.ROISetColor(0,1,0)
roi2.ROISetDrawFilled(1)
roi2.ROISetFillProperties(0.2,0,0.1,0)
ROI roi3 = NewROI()
roi3.ROISetRectangle( 150, 150, 250, 250 )
roi3.ROISetVolatile(0)
roi3.ROISetColor(0,0,1)
roi3.ROISetDrawFilled(1)
roi3.ROISetFillProperties(0.2,0,0,0.1)
disp.ImageDisplayAddROI( roi1 )
disp.ImageDisplayAddROI( roi2 )
disp.ImageDisplayAddROI( roi3 )
OKDialog( "Now send blue to the bottom" )
disp.ImageDisplayDeleteROI( roi3 )
disp.ImageDisplayAddROIAtBeginning( roi3 )
OKDialog( "Now send red to front" )
disp.ImageDisplayDeleteROI( roi1 )
disp.ImageDisplayAddROIAtEnd( roi1 )

Related

How to add a color or calibration bar

I would like to append a color bar to my image to indicate what value corresponds to which color.
Something similar to the calibration bar in ImageJ.
Thank you for your help
What you are looking for is the "Intensity bar".
Example script right from the F1 help documenation:
image img := RealImage("Test",4,512,512)
img = itheta
img.ShowImage()
imageDisplay disp = img.ImageGetImageDisplay(0)
number kSCALEBAR = 31
number kINTENSITYBAR = 33
component scalebar = NewComponent( kSCALEBAR, 450, 100, 480, 300 )
disp.ComponentAddChildAtEnd( scalebar )
component intbar = NewComponent( kINTENSITYBAR, 50, 400, 450, 490 )
disp.ComponentAddChildAtEnd( intbar )

Tesseract and multiple line license plates: How can I get characters from a two line license plate?

i tried getting individual characters from the image and passing them through the ocr, but the result is jumbled up characters. Passing the whole image is at least returning the characters in order but it seems like the ocr is trying to read all the other contours as well.
example image:
Image being used
The result : 6A7J7B0
Desired result : AJB6779
The code
img = cv2.imread("data/images/car6.jpg")
gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
# resize image to three times as large as original for better readability
gray = cv2.resize(gray, None, fx = 3, fy = 3, interpolation = cv2.INTER_CUBIC)
# perform gaussian blur to smoothen image
blur = cv2.GaussianBlur(gray, (5,5), 0)
# threshold the image using Otsus method to preprocess for tesseract
ret, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_OTSU | cv2.THRESH_BINARY_INV)
# create rectangular kernel for dilation
rect_kern = cv2.getStructuringElement(cv2.MORPH_RECT, (5,5))
# apply dilation to make regions more clear
dilation = cv2.dilate(thresh, rect_kern, iterations = 1)
# find contours of regions of interest within license plate
try:
contours, hierarchy = cv2.findContours(dilation, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
except:
ret_img, contours, hierarchy = cv2.findContours(dilation, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
# sort contours left-to-right
sorted_contours = sorted(contours, key=lambda ctr: cv2.boundingRect(ctr)[0])
# create copy of gray image
im2 = gray.copy()
# create blank string to hold license plate number
plate_num = ""
# loop through contours and find individual letters and numbers in license plate
for cnt in sorted_contours:
x,y,w,h = cv2.boundingRect(cnt)
height, width = im2.shape
# if height of box is not tall enough relative to total height then skip
if height / float(h) > 6: continue
ratio = h / float(w)
# if height to width ratio is less than 1.5 skip
if ratio < 1.5: continue
# if width is not wide enough relative to total width then skip
if width / float(w) > 15: continue
area = h * w
# if area is less than 100 pixels skip
if area < 100: continue
# draw the rectangle
rect = cv2.rectangle(im2, (x,y), (x+w, y+h), (0,255,0),2)
# grab character region of image
roi = thresh[y-5:y+h+5, x-5:x+w+5]
# perfrom bitwise not to flip image to black text on white background
roi = cv2.bitwise_not(roi)
# perform another blur on character region
roi = cv2.medianBlur(roi, 5)
try:
text = pytesseract.image_to_string(roi, config='-c tessedit_char_whitelist=0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ --psm 8 --oem 3')
# clean tesseract text by removing any unwanted blank spaces
clean_text = re.sub('[\W_]+', '', text)
plate_num += clean_text
except:
text = None
if plate_num != None:
print("License Plate #: ", plate_num)
For me psm mode 11 worked able to detect single line and multi as well
pytesseract.image_to_string(img, lang='eng', config='--oem 3 --psm 11').replace("\n", ""))
11 Sparse text. Find as much text as possible in no particular order.
If you want to extract license plate number from two rows you can replace following line:
sorted_contours = sorted(contours, key=lambda ctr: cv2.boundingRect(ctr)[0] + cv2.boundingRect(ctr)[1] * img.shape[1] )
with
sorted_contours = sorted(contours, key=lambda ctr: cv2.boundingRect(ctr)[0])

The code/command to determine/change the length/height ratio of scale bar?

I would like to adjust the length/height ratio of the scale bar in an image by the DM scripting. As the following code shown, I can adjust the font size by changing "scalebar.componentsetfontinfo("Microsoft Sans Serif", 0, fontsize)", but I do not know how to change the shape (length/height ratio) of rectangle which constitute to the scale bar. Is there any code/command can achieve this? Thanks,
image front:=getfrontimage()
imagedisplay imgdisp=front.imagegetimagedisplay(0)
number nobar=imgdisp.componentcountchildrenoftype(31)
number fontsize=20
imgdisp.applydatabar(0)
component scalebar=imgdisp.componentgetnthchildoftype(31,0)
scalebar.componentsetfontinfo("Microsoft Sans Serif", 0, fontsize)
scalebar.componentsetdrawingmode(1)
When you select a scalebar, you will notice the green points showing that component's rectangle.
You control that rectangle like you control any component rectangle:
number kScaleBar = 31
image img := GetFrontImage()
imageDisplay disp = img.ImageGetImageDisplay(0)
component scaleBar = disp.ComponentGetNthChildOfType( kScaleBar, 0 )
number t,l,b,r
scaleBar.ComponentGetRect(t,l,b,r)
Result("\n Current rect: [" + t + "/" + l + "/" + b + "/" + r )
number sx, sy
img.GetSize( sx, sy )
// Set centered half at bottom
l = sx*1/4
r = sx*3/4
t = sy*17/20
b = sy*19/20
scaleBar.ComponentSetRect(t,l,b,r)
Note, that you can not explicitly specify the length of the scalebar, it will always "snap" to a meaningful fraction within the boundary box, depending on the image calibration.
Setting the bounding rect will also override the font-size, while setting the font-size will override the boundary rect's height.

How to get the correct shape position

shape = new createjs.Shape();
shape.graphics.beginFill('#000').drawCircle(100, 0, 6);
shape.x = 100;
shape.y = 100;
stage.addChild(shape);
stage.update();
When I use this code, the shape is placed at the point(200,100). Why is it not placed at point(100,100) instead?
What does it mean "the shape is placed at the point (200, 100) ?".
Actually, the drawing is made according to the top left corner of the shape.
Your shape is certainly drawn in (100, 100) but as the circle diameter is 100px, it will be drawn from the point (100, 100) to the point (200, 200).

How can I select a subarea of an image with mouse and make it a new image?

I want to get some subarea of an image and make it a new image, and then execute further functions on it.
How can I use mouse to select a subarea of an image?
I know img[] could get the subarea of img, but I need some function by which I can interact with img. I mean, I want to get a WYSIWYG effect.
Is there any commands available, or is there any methods of ROI capable?
There different ways to do what you want in a script: You could ask the user to place an ROI and then use the [] to address this area. If you want to get a new image from this selection (CTRL + C and CTRL + SHIFT + V without scripting) you would write:
ShowImage( ImageClone( img[] ) )orimg[].ImageClone().ShowImage()
If you want to place a ROI for the user, you can used SetSelection() for a simple, rectangle, volatile ROI, or you use the full ROI commands like in this example:
image img := RealImage( "Test", 4, 256, 256 ) // create image
img.ShowImage() // show the image (so that it has a display)
imageDisplay disp = img.ImageGetImageDisplay(0) // Get the 'display' of an image
ROI myR = NewRoi() // create ROI
myR.ROISetRectangle( 110, 120, 130, 140 ) // Make it a rectangle of given area
myR.ROISetVolatile( 0 ) // make it non-volatile
myR.ROISetLabel( "Selection" ) // give it a label
myR.ROISetColor( 0, 1, 0 ) // make it green
disp.ImageDisplayAddROI( myR ) // add it to the display
A full list of ROI commands can be found in the following section of the F1 help documentation: