The code to set placement and font size of caption/legend of line plot image in DM - dm-script

Try to get the code to set placement and font size of caption/legend of line plot image by DM scripting, as show in the attached pics, can not find them in the help files, only get LinePlotImageDisplayIsLegendShown, any suggestions? thx

Multiple questions, so one at a time
The legend section of a lineplot can not be altered. It can only be shown or hidden. It's size and position is always automatically determined by the application.
The caption font and text size can not be altered by script with the current version of GMS. You may want to file a feature-request for such a script command here: Gatan issue/bug submission form.
The placement coordinates of the window in your screen-shot represents just the coordinates and size of the image window on the workspace and not any of the lineplot content. So you would set it like:
image plot := RealImage("Plot",4,500)
plot = sin( icol/iwidth*5*pi() )
plot.ShowImage()
ImageDocument doc = plot.ImageGetOrCreateImageDocument()
DocumentWindow win = doc.ImageDocumentGetWindow()
number posX = 100
number posY = 50
win.WindowSetFramePosition( posX, posY )
number w = 1200
number h = 200
win.WindowSetFrameSize( w, h )
More commands on window placement are found here:

Related

Add ROI to 1D image (intensity plot etc.)

Try to add ROI of determined position to 1D image (intensity plot, or line scan proflie). It does not work, could not find the function by google, is there correct codes?
number d0, d1
image spc:=getFrontImage()
spc.getSize(d0,d1)
imagedisplay imgdisp = spc.ImageGetImageDisplay(0)
ROI roi_1 = NewROI()
ROISetRectangle( roi_1, 0, 100,d1 , 200 )
imgdisp.ImageDisplayAddROI( roi_1)
imagedisplaysetroiselected(imgdisp, roi_1,1)
The exact error message when running your code is:
This very accurately tells you the problem: Not all types of ROIS (Rectangle, Line, Lasso, Point,...) are suitable for all kind of displays. In particular, you can't draw a rectangle-ROI on a LinePlot display.
In fact, LinePlot displays support a single type of ROI: Range-ROIs.
So, the code for you problem is:
image spc:=getFrontImage()
imagedisplay imgdisp = spc.ImageGetImageDisplay(0)
ROI roi_1 = NewROI()
ROISetRange( roi_1, 100, 200 )
imgdisp.ImageDisplayAddROI( roi_1)
imagedisplaysetroiselected(imgdisp, roi_1,1)

OpenCV detect blobs on the image

I need to find (and draw rect around)/get max and min radius blobs on the image. (samples below)
the problem is to find correct filters for the image that will allow Canny or Threshold transformation to highlight the blobs. then I going to use findContours to find the rectangles.
I've tryed:
Threshold - with different level
blur->erode->erode->grayscale->canny
change image tone with variety of "lines"
and ect. the better result was to detect piece (20-30%) of blob. and this info not allowed to draw rect around blob. also, thanks for shadows, not related to blob dots were detected, so that also prevents to detect the area.
as I understand I need to find counter that has hard contrast (not smooth like in shadow). Is there any way to do that with openCV?
Update
cases separately: image 1, image 2, image 3, image 4, image 5, image 6, image 7, image 8, image 9, image 10, image 11, image 12
One more Update
I believe that the blob have the contrast area at the edge. So, I've tried to make edge stronger: I've created 2 gray scale Mat: A and B, apply Gaussian blur for the second one - B (to reduce noise a bit), then I've made some calculations: goes around every pixel and find max difference between Xi,Yi of 'A' and nearby dots from 'B':
and apply max difference to Xi,Yi. so I get smth like this:
is i'm on the right way? btw, can I reach smth like this via OpenCV methods?
Update Image Denoising helps to reduce noize, Sobel - to highlight the contours, then threshold + findContours and custome convexHull gets smth similar I'm looking for but it not good for some blobs.
Since there are big differences between the input images, the algorithm should be able to adapt to the situation. Since Canny is based on detecting high frequencies, my algorithm treats the sharpness of the image as the parameter used for preprocessing adaptation. I didn't want to spend a week figuring out the functions for all the data, so I applied a simple, linear function based on 2 images and then tested with a third one. Here are my results:
Have in mind that this is a very basic approach and is only proving a point. It will need experiments, tests, and refining. The idea is to use Sobel and sum over all the pixels acquired. That, divided by the size of the image, should give you a basic estimation of high freq. response of the image. Now, experimentally, I found values of clipLimit for CLAHE filter that work in 2 test cases and found a linear function connecting the high freq. response of the input with a CLAHE filter, yielding good results.
sobel = get_sobel(img)
clip_limit = (-2.556) * np.sum(sobel)/(img.shape[0] * img.shape[1]) + 26.557
That's the adaptive part. Now for the contours. It took me a while to figure out a correct way of filtering out the noise. I settled for a simple trick: using contours finding twice. First I use it to filter out the unnecessary, noisy contours. Then I continue with some morphological magic to end up with correct blobs for the objects being detected (more details in the code). The final step is to filter bounding rectangles based on the calculated mean, since, on all of the samples, the blobs are of relatively similar size.
import cv2
import numpy as np
def unsharp_mask(img, blur_size = (5,5), imgWeight = 1.5, gaussianWeight = -0.5):
gaussian = cv2.GaussianBlur(img, (5,5), 0)
return cv2.addWeighted(img, imgWeight, gaussian, gaussianWeight, 0)
def smoother_edges(img, first_blur_size, second_blur_size = (5,5), imgWeight = 1.5, gaussianWeight = -0.5):
img = cv2.GaussianBlur(img, first_blur_size, 0)
return unsharp_mask(img, second_blur_size, imgWeight, gaussianWeight)
def close_image(img, size = (5,5)):
kernel = np.ones(size, np.uint8)
return cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel)
def open_image(img, size = (5,5)):
kernel = np.ones(size, np.uint8)
return cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)
def shrink_rect(rect, scale = 0.8):
center, (width, height), angle = rect
width = width * scale
height = height * scale
rect = center, (width, height), angle
return rect
def clahe(img, clip_limit = 2.0):
clahe = cv2.createCLAHE(clipLimit=clip_limit, tileGridSize=(5,5))
return clahe.apply(img)
def get_sobel(img, size = -1):
sobelx64f = cv2.Sobel(img,cv2.CV_64F,2,0,size)
abs_sobel64f = np.absolute(sobelx64f)
return np.uint8(abs_sobel64f)
img = cv2.imread("blobs4.jpg")
# save color copy for visualizing
imgc = img.copy()
# resize image to make the analytics easier (a form of filtering)
resize_times = 5
img = cv2.resize(img, None, img, fx = 1 / resize_times, fy = 1 / resize_times)
img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# use sobel operator to evaluate high frequencies
sobel = get_sobel(img)
# experimentally calculated function - needs refining
clip_limit = (-2.556) * np.sum(sobel)/(img.shape[0] * img.shape[1]) + 26.557
# don't apply clahe if there is enough high freq to find blobs
if(clip_limit < 1.0):
clip_limit = 0.1
# limit clahe if there's not enough details - needs more tests
if(clip_limit > 8.0):
clip_limit = 8
# apply clahe and unsharp mask to improve high frequencies as much as possible
img = clahe(img, clip_limit)
img = unsharp_mask(img)
# filter the image to ensure edge continuity and perform Canny
# (values selected experimentally, using trackbars)
img_blurred = (cv2.GaussianBlur(img.copy(), (2*2+1,2*2+1), 0))
canny = cv2.Canny(img_blurred, 35, 95)
# find first contours
_, cnts, _ = cv2.findContours(canny.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
# prepare black image to draw contours
canvas = np.ones(img.shape, np.uint8)
for c in cnts:
l = cv2.arcLength(c, False)
x,y,w,h = cv2.boundingRect(c)
aspect_ratio = float(w)/h
# filter "bad" contours (values selected experimentally)
if l > 500:
continue
if l < 20:
continue
if aspect_ratio < 0.2:
continue
if aspect_ratio > 5:
continue
if l > 150 and (aspect_ratio > 10 or aspect_ratio < 0.1):
continue
# draw all the other contours
cv2.drawContours(canvas, [c], -1, (255, 255, 255), 2)
# perform closing and blurring, to close the gaps
canvas = close_image(canvas, (7,7))
img_blurred = cv2.GaussianBlur(canvas, (8*2+1,8*2+1), 0)
# smooth the edges a bit to make sure canny will find continuous edges
img_blurred = smoother_edges(img_blurred, (9,9))
kernel = np.ones((3,3), np.uint8)
# erode to make sure separate blobs are not touching each other
eroded = cv2.erode(img_blurred, kernel)
# perform necessary thresholding before Canny
_, im_th = cv2.threshold(eroded, 50, 255, cv2.THRESH_BINARY)
canny = cv2.Canny(im_th, 11, 33)
# find contours again. this time mostly the right ones
_, cnts, _ = cv2.findContours(canny.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# calculate the mean area of the contours' bounding rectangles
sum_area = 0
rect_list = []
for i,c in enumerate(cnts):
rect = cv2.minAreaRect(c)
_, (width, height), _ = rect
area = width*height
sum_area += area
rect_list.append(rect)
mean_area = sum_area / len(cnts)
# choose only rectangles that fulfill requirement:
# area > mean_area*0.6
for rect in rect_list:
_, (width, height), _ = rect
box = cv2.boxPoints(rect)
box = np.int0(box * 5)
area = width * height
if(area > mean_area*0.6):
# shrink the rectangles, since the shadows and reflections
# make the resulting rectangle a bit bigger
# the value was guessed - might need refinig
rect = shrink_rect(rect, 0.8)
box = cv2.boxPoints(rect)
box = np.int0(box * resize_times)
cv2.drawContours(imgc, [box], 0, (0,255,0),1)
# resize for visualizing purposes
imgc = cv2.resize(imgc, None, imgc, fx = 0.5, fy = 0.5)
cv2.imshow("imgc", imgc)
cv2.imwrite("result3.png", imgc)
cv2.waitKey(0)
Overall I think that's a very interesting problem, a little bit too big to be answered here. The approach I presented is due to be treated as a road sign, not a complete solution. Tha basic idea being:
Adaptive preprocessing.
Finding contours twice: for filtering and then for the actual classification.
Filtering the blobs based on their mean size.
Thanks for the fun and good luck!
Here is the code I used:
import cv2
from sympy import Point, Ellipse
import numpy as np
x1='C:\\Users\\Desktop\\python\\stack_over_flow\\XsXs9.png'
image = cv2.imread(x1,0)
image1 = cv2.imread(x1,1)
x,y=image.shape
median = cv2.GaussianBlur(image,(9,9),0)
median1 = cv2.GaussianBlur(image,(21,21),0)
a=median1-median
c=255-a
ret,thresh1 = cv2.threshold(c,12,255,cv2.THRESH_BINARY)
kernel=np.ones((5,5),np.uint8)
dilation = cv2.dilate(thresh1,kernel,iterations = 1)
kernel=np.ones((5,5),np.uint8)
opening = cv2.morphologyEx(dilation, cv2.MORPH_OPEN, kernel)
cv2.imwrite('D:\\test12345.jpg',opening)
ret,contours,hierarchy = cv2.findContours(opening,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
c=np.size(contours[:])
Blank_window=np.zeros([x,y,3])
Blank_window=np.uint8(Blank_window)
for u in range(0,c-1):
if (np.size(contours[u])>200):
ellipse = cv2.fitEllipse(contours[u])
(center,axes,orientation) =ellipse
majoraxis_length = max(axes)
minoraxis_length = min(axes)
eccentricity=(np.sqrt(1-(minoraxis_length/majoraxis_length)**2))
if (eccentricity<0.8):
cv2.drawContours(image1, contours, u, (255,1,255), 3)
cv2.imwrite('D:\\marked.jpg',image1)
Here problem is to find a near circular object. This simple solution is based on finding the eccentricity for each and every contour. Such objects being detected is the drop of water.
I have a partial solution in place.
FIRST
I initially converted the image to the HSV color space and tinkered with the value channel. On doing so I came across something unique. In almost every image, the droplets have a tiny reflection of light. This was highlighted distinctly in the value channel.
Upon inverting this I was able to obtain the following:
Sample 1:
Sample 2:
Sample 3:
SECOND
Now we have to extract the location of those points. To do so I performed anomaly detection on the inverted value channel obtained. By anomaly I mean the black dot present in them.
In order to do this I calculated the median of the inverted value channel. I allotted pixel value within 70% above and below the median to be treated as normal pixels. But every pixel value lying beyond this range to be anomalies. The black dots fit perfectly there.
Sample 1:
Sample 2:
Sample 3:
It did not turn out well for few images.
As you can see the black dot is due to the reflection of light which is unique to the droplets of water. Other circular edges might be present in the image but the reflection distinguishes the droplet from those edges.
THIRD
Now since we have the location of these black dots, we can perform Difference of Gaussians (DoG) (also mentioned in the update of the question) and obtain relevant edge information. If the obtained location of the black dots lie within the edges discovered it is said to be a water droplet.
Disclaimer: This method does not work for all the images. You can add your suggestions to this.
Good day , I am working on this subject and my advice to you is; First, after using many denoising filters such as Gaussian filters, process the image after that.
You can blob-detection these circles not with countors.

MDAnalysis selects atoms from the PBC box but does not shift the coordinates

MDAnalysis distance selection commands like 'around' and 'sphzere' selects atoms from periodic image (I am using a rectangular box).
universe.select_atoms("name OW and around 4 (resid 20 and name O2)")
However, the coordinates of the atoms from the PBC box reside on the other side of the box. In other words, I have to manually translate the atoms to ensure that they actually are withing the 4 Angstrom distance.
Is there a selection feature to achieve this using the select_atoms function?
If I well understand, you would like to get the atoms around a given selection in the image that is the closest to that selection.
universe.select_atoms does not modify the coordinates, and I am not aware of a function that gives you what you want. The following function could work for an orthorhombic box like yours:
def pack_around(atom_group, center):
"""
Translate atoms to their periodic image the closest to a given point.
The function assumes that the center is in the main periodic image.
"""
# Get the box for the current frame
box = atom_group.universe.dimensions
# The next steps assume that all the atoms are in the same
# periodic image, so let's make sure it is the case
atom_group.pack_into_box()
# AtomGroup.positions is a property rather than a simple attribute.
# It does not always propagate changes very well so let's work with
# a copy of the coordinates for now.
positions = atom_group.positions.copy()
# Identify the *coordinates* to translate.
sub = positions - center
culprits = numpy.where(numpy.sqrt(sub**2) > box[:3] / 2)
# Actually translate the coordinates.
positions[culprits] -= (u.dimensions[culprits[1]]
* numpy.sign(sub[culprits]))
# Propagate the new coordinates.
atom_group.positions = positions
Using that function, I got the expected behavior on one of MDAnalysis test files. You need MDAnalysisTests to be installed to run the following piece of code:
import numpy
import MDAnalysis as mda
from MDAnalysisTests.datafiles import PDB_sub_sol
u = mda.Universe(PDB_sub_sol)
selection = u.select_atoms('around 15 resid 32')
center = u.select_atoms('resid 32').center_of_mass()
# Save the initial file for latter comparison
u.atoms.write('original.pdb')
selection.write('selection_original.pdb')
# Translate the coordinates
pack_around(selection, center)
# Save the new coordinates
u.atoms.write('modified.pdb')
selection.write('selection_modified.pdb')

Convert Image into Flag

I have to change any given picture into the Pride flag.
To do so, my current code is:
pixels = getPixels(picture)
width = getWidth(picture)
height = getHeight(picture)
for index in range(0,len(pixels)/7):
pixel = pixels[index]
setColor(pixel,red)
for index in range(len(pixels)/7,len(pixels)):
pixel = pixels[index]
setColor(pixel,orange)
for index in range(2*len(pixels)/7,len(pixels)):
pixel = pixels[index]
setColor(pixel,yellow)
Note: I have not included the entire code snippet, it continues on in that same manner.
The problem is that the lines colours are interjecting into each other and it shows up as this:
What could be causing this and how do I go about fixing it?
It would seem there is an uneven about of pixels for the line divisions you are doing. Find out how many pixels there are for each line then use that in your for loops. For example...
no_pixels_per_line = len(pixels) / height
for index in range(0, (height/7) * no_pixels_per_line):
pixel = pixels[index]
setColor(pixel,red)
etc...

Jython: Need to open two picture and copy the 2nd picture to the 1st's picture bottom right Corner (Sorta like a logo)

I am trying to copy pic2 to pic1's bottom right corner (Adding a logo to a picture) Im pretty sure this is the part of the code that im having difficulty with as I cannot figure out whats next after the two getPixel statements.
for x in range(0, getWidth(pic2)):
for y in range(0, getHeight(pic2)):
p1 = getPixel(pic1, x, y)
p2 = getPixel(pic2, x, y)
setPixel = p1
Assuming one image is bigger than the other, you don't need to collect pixels from both picture objects, just the logo.
Seems like this might be homework so I'll just help you along.
for x in range(0, getWidth(pic2)):
for y in range(0, getHeight(pic2)):
p1 = getPixel(pic2, x, y)
p1Col = getColor(p1)
Also, your nested for loops will start in the top left of the image, to apply the logo in the bottom right we use some simple math after getting the logo pixel color.
imageWidth - logoWidth + x - 1
Where the -1 is to prevent the logo exceeding the image width.
Use that same style of formula for the height.