-
Notifications
You must be signed in to change notification settings - Fork 0
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
Bugfix/sci cam sign flip #124
base: develop
Are you sure you want to change the base?
Conversation
make_property_helper('rot90') | ||
make_property_helper('flip_x') | ||
make_property_helper('flip_y') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't we want them to be read-only?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good look, I agree and will update both here and in the flir_camera
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
@raphaelpclt brought up a good point that we currently have the functionality to update the offset_x and offset_y on the fly and these changes would result in unexpected behavior for that. We can define the offset_x and offset_y to be with respect to the transformed (rotated and/or flipped) coordinate system in the yml to preserve this functionality and then convert those values to camera array coordinates to be passed to the internal camera getROI functions. My only thoughts against this option are that we would then have two different offset_x and offset_y conventions that may lead to some confusion down the road |
@steigersg Yes, I want the I was for not even showing the actual We could use a suffix |
img = np.flipud(img) | ||
if self.flip_y: | ||
img = np.fliplr(img) | ||
return img |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
does not result in C Contiguous array - working on it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is expected and desired. This is what makes it fast to run multiple of these operations in a row.
Some benchmarks for just the nothing: only rot90: only flip_x: flip_x + flip_y: rot90 + flip_x: copy to contiguous array with rot90: copy to contiguous array without rot90: So the copy takes by far the most time. I just noticed that all these benchmarks were done with float64, not float32 dtype. But the copy takes about the same amount of time, likely because cache access in weird ordering takes the most time rather than the memory copying itself (ie. no/little acceleration from SIMD instructions or something). Losing a full millisecond is not great, but for these large array sizes, we're not gonna run that fast anyways. For smaller array sizes (eg. 312x312, float32 as for our zernike camera), the same benchmark is |
For comparison, on the same machine: submitting 1024x1024 float32 on data stream (which copies the data internally): copying 1024x1024 float32 with |
Just tested as well: using a.T (as an alternative to rot90) with ascontiguousarray: so the same speed as the rot90 for float32. |
…s and the x and y offsets to apply in camera array coordinates.
self.rot90 = rot90 | ||
self.flip_x = flip_x | ||
self.flip_y = flip_y |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you can set these straight from the config. I don't see a need to have them as local variables first. Also, this might need to be moved up to before you're actually setting offset_x/y and width/height on the camera, since they need these to exist.
make_property_helper('rot90', read_only=True) | ||
make_property_helper('flip_x', read_only=True) | ||
make_property_helper('flip_y', read_only=True) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need these as properties? Or can we have them in the CameraProxy
object instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't have an intuition for what the pros and cons of having them in the CameraProxy vs. here would be. I agree though they don't necessarily have to be properties since they're only used in the rot_flip_image
and get_camera_offset
functions and could easily be key word arguments in there
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To give some context, I'm not talking about Python properties. I'm talking about catkit2 properties, which is what the make_property_helper() function is creating. Those properties are available from the outside, ie. from client-side. Communication is done via TCP, which is not necessary. Since they are read-only and they are never meant to be changed/changable, their value can be purely gotten from the config file. Therefore, no communication between ServiceProxy and Service needs to take place, making it much easier to get the right value straight from the config in the ServiceProxy.
""" | ||
# Define the translation matrix T to get to the center of the ROI. | ||
T = np.zeros((3, 3)) | ||
np.fill_diagonal(T, 1) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd construct the matrix with np.eye(3)
instead rather than creating them as zeros and then filling the diagonal with ones. The same for the other matrices.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks! I forgot np.eye existed - updated that code for all the matrices where I wanted diagonals filled
if self.flip_x: | ||
# Define x reflection matrix. | ||
X[0][0] = -1 | ||
|
||
if self.flip_y: | ||
# Define y reflection matrix. | ||
Y[1][1] = -1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't the flips also need translation matrices, since the flips are reflections around the centerlines of the images?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good catch! moved the final translation to after the x and y flips
|
||
self.width = self.config.get('width', self.sensor_width - offset_x) | ||
self.height = self.config.get('height', self.sensor_height - offset_y) | ||
|
||
offset_x, offset_y = self.get_camera_offset(offset_x, offset_y) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The properties height, width, offset_x and offset_y need to be modified instead. Otherwise, setting the offset_x and offset_y dynamically won't work as expected.
self.width = self.config.get('width', self.sensor_width - offset_x) | ||
self.height = self.config.get('height', self.sensor_height - offset_y) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't the width/height properties need to be changed as well? To exchange width/height that is.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if rot90 is True I updated the code so that the width and height properties are swapped. This could cause issues though if the get_camera_offset function hasn't been called yet (since it needs to know the previous origin location) so I also added an in-line comment to warn agains this.
Should be superseded with camera base class #131 |
See affiliated PR on hicat-package2 (https://github.com/spacetelescope/hicat-package2/pull/480)
Add infrastructure in camera services to rotate and/or flip the images on the camera.
The camera rotation happens first and defines which camera axis (width or height) is aligned with the gravity vector of the testbed. Defining
rot90
to beTrue
will perform one counter-clockwise 90 degree rotation. If a clockwise rotation is desired thenflip_y
should also be set toTrue
.The flips (
flip_x
, andflip_y
), with the exception of the example above, are meant to be defined with respect to the optical axis (e.g. whether a lens upstream of the camera has flipped the image).Notably
offset_x
andoffset_y
values are not changed with the reflections and rotations since these are fundamentally defined with respect to the camera array and the setters and getters for these values are directly given to the setROI functions in the vendor camera control software itself. I believe this is alright since finding these values should not have to occur very frequently and the user can take care to make sure they are defined with respect to the coordinate system of the camera itself.Tasks before review