Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AreaDetector_Display: Draw lines on top of camera image #15

Open
zunbeltz opened this issue Jun 11, 2015 · 6 comments
Open

AreaDetector_Display: Draw lines on top of camera image #15

zunbeltz opened this issue Jun 11, 2015 · 6 comments

Comments

@zunbeltz
Copy link

My aim is to draw some lines on top of the image. As far as I understood how imageview works,
it should be done directly on the DrawImage method using de dc instance (unless we do it a instance attribute). I plugged the following line in the code:

dc.DrawLine(512*xscale,0*yscale, 512*xscale, 1024*yscale)

But it doesn't seem to be a line on the center in my 1024x1024 image.
The image it also not shown completely on the frame even if the application is maximaized.

@newville
Copy link
Member

@zunbeltz I think that should work, though it wasn't clear to me what was being shown (like, is there a line, but it's just in the wrong place?). Perhaps the values to dc.DrawLine really need to be ints? I think you might want to get the actual size of the bitmap being drawn, using something like:

bitmap = wx.BitmapFromImage(wximage)
bitmap_width, bitmap_height  = bitmap.GetSize()
dc = wx.AutoBufferedPaintDC(wxpanel)
dc.DrawBitmap(bitmap, 0,  0, useMask=True)
dc.BeginDrawing()
dc.SetPen(wx.Pen('Red', 1.5, wx.SOLID))
dc.DrawLine(0, bitmap_height/2, bitmap_width, bitmap_height/2)
dc.EndDrawing()

That is, you're drawing on the bitmap, not the image, and it might be simpler to work in bitmap coordinates.

Another option for simple lines is to use the AreaDetector overlay feature. That would add the line to the incoming arraydata. It's not as flexible as drawing on the image with wx, but can draw lines.

@zunbeltz
Copy link
Author

@newville This code snippest work fine. I put it in viewimage.py lines 192-200:

bitmap = wx.BitmapFromImage(img)
bitmap_width, bitmap_height  = bitmap.GetSize()    
dc = wx.AutoBufferedPaintDC(self)
dc.DrawBitmap(bitmap, 0,  0, useMask=True)
dc.BeginDrawing()
dc.SetPen(wx.Pen('Red', 1.5, wx.SOLID))
dc.DrawLine(0, bitmap_height/2, bitmap_width, bitmap_height/2)
dc.DrawLine(bitmap_width/2, 0, bitmap_width/2, bitmap_height)
dc.EndDrawing()

And the lines apear on the center of the image.
Anoter problem is that the appilication is taller than my screen and I don't see the bottom part.
So know I just need to scale my data coordinates to the bitmap_width and height.

Is there any way to put this code outside the ImageView class?
Can I attach more than one "device context" to the same wxPanel? I would prefer to put it on a method of AD_Display.

@newville
Copy link
Member

@zunbeltz I'm not sure I understand the question. What code do you want to put outside ImageView? You mean code about the device context?

In general, I think ImageView and AD_Display could be greatly improved. I've been playing recently with an alternative (simpler) implementation, which is currently incomplete in sampleviewer/lib/imagepanel_epicsAD.py, and this should probably be used for an improved AD_Display. It would be perfectly reasonable (though details would need to be worked out) to think about add lines and other objects drawn over the image to a wxPanel that showed an areadetector image.

I'm not sure it is possible to attach more than one device context to a wxPanel. What do you have in mind?

@zunbeltz
Copy link
Author

Yes. I was thinking of putting the code that draws the lines outside the
ImageViewer. Maybe it is enough to set the dc as a instance attribute of
the ImageViewer, so I can call methods to draw of it from the AD_Display
class.
I will try tomorrow the sampleviewer application to see if I can use it.

og., 2015.eko ekaren 11a 17:36(e)an, Matt Newville igorleak idatzi zuen:

@zunbeltz https://github.com/zunbeltz I'm not sure I understand the
question. What code do you want to put outside ImageView? You mean
code about the device context?

In general, I think ImageView and AD_Display could be greatly
improved. I've been playing recently with an alternative (simpler)
implementation, which is currently incomplete in
|sampleviewer/lib/imagepanel_epicsAD.py|, and this should probably be
used for an improved AD_Display. It would be perfectly reasonable
(though details would need to be worked out) to think about add lines
and other objects drawn over the image to a wxPanel that showed an
areadetector image.

I'm not sure it is possible to attach more than one device context to
a wxPanel. What do you have in mind?


Reply to this email directly or view it on GitHub
#15 (comment).

@newville
Copy link
Member

@zunbeltz Generally on creates, uses, and completes a dc object as quickly as possible inside a "paint" operation. So, I don't think having this exposed outside of the wxPanel subclass is a good idea (even if it could be made to work).

But: I also want to be able to specify a few lines, circles, etc to be drawn on the image panel. I'm thinking of adding a "draw_objects" argument that is a list of dicts that specifies (shape, color, linewidth, and size), perhaps

draw_objects=[{'shape': 'line', 'color': 'Red', 'linewidth': 1.5, 'args': (0.5, 0, 0,5, 1)}, 
                       {'shape': 'circle', 'color': 'Blue', 'linewidth': 1, 'args': (0.5, 0.5, 0.02)}]

which would use fractional coordinates, and get converted to the right dc.SetPen, dc.DrawLine, and dc.DrawCircle calls. I'm hoping to work on this over the next week or two, and update AD_Display() based on the simpler code in epicsapps/sampleviewer. Does that seem reasonable to you?

FWIW, I'm also thinking of reorganizing all the epicsapp code into a single module, as it's becoming obvious that we need high-level, reusable GUI components.

@zunbeltz
Copy link
Author

Finally I got working whar I need. I just pass the calculated points to the
imageview.

What I did is just a hack, no very elegant code.

I will follow with interest the changes. I maybe can help testing or with
some code.
El 12/06/2015 14:48, "Matt Newville" notifications@github.com escribió:

@zunbeltz https://github.com/zunbeltz Generally on creates, uses, and
completes a dc object as quickly as possible inside a "paint" operation.
So, I don't think having this exposed outside of the wxPanel subclass is a
good idea (even if it could be made to work).

But: I also want to be able to specify a few lines, circles, etc to be
drawn on the image panel. I'm thinking of adding a "draw_objects" argument
that is a list of dicts that specifies (shape, color, linewidth, and size),
perhaps

draw_objects=[{'shape': 'line', 'color': 'Red', 'linewidth': 1.5, 'args': (0.5, 0, 0,5, 1)},
{'shape': 'circle', 'color': 'Blue', 'linewidth': 1, 'args': (0.5, 0.5, 0.02)}]

which would use fractional coordinates, and get converted to the right
dc.SetPen, dc.DrawLine, and dc.DrawCircle calls. I'm hoping to work on
this over the next week or two, and update AD_Display() based on the
simpler code in epicsapps/sampleviewer. Does that seem reasonable to you?

FWIW, I'm also thinking of reorganizing all the epicsapp code into a
single module, as it's becoming obvious that we need high-level, reusable
GUI components.


Reply to this email directly or view it on GitHub
#15 (comment).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants