Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion RMS/Astrometry/ApplyRecalibrate.py
Original file line number Diff line number Diff line change
Expand Up @@ -405,7 +405,7 @@ def recalibratePlateparsForFF(

# Get stars detected on this FF file (create a dictionaly with only one entry, the residuals function
# needs this format)
calstars_time = FFfile.getMiddleTimeFF(ff_name, config.fps, ret_milliseconds=True)
calstars_time = FFfile.getMiddleTimeFF(ff_name, config.fps, ret_milliseconds=True,ff_frames=config.frames_per_block)
jd = date2JD(*calstars_time)
star_dict_ff = {jd: calstars[ff_name]}

Expand Down
6 changes: 3 additions & 3 deletions RMS/Astrometry/CheckFit.py
Original file line number Diff line number Diff line change
Expand Up @@ -403,7 +403,7 @@ def starListToDict(config, calstars_list, max_ffs=None):
if len(stars_list) >= config.ff_min_stars:

# Calculate the JD time of the FF file
dt = FFfile.getMiddleTimeFF(ff_name, config.fps, ret_milliseconds=True)
dt = FFfile.getMiddleTimeFF(ff_name, config.fps, ret_milliseconds=True,ff_frames=config.frames_per_block)
jd = date2JD(*dt)

# Add the time and the stars to the dict
Expand Down Expand Up @@ -465,7 +465,7 @@ def _handleFailure(config, platepar, calstars_list, catalog_stars, _fft_refineme
calstars_coords[:, [0, 1]] = calstars_coords[:, [1, 0]]

# Get the time of the FF file
calstars_time = FFfile.getMiddleTimeFF(max_len_ff, config.fps, ret_milliseconds=True)
calstars_time = FFfile.getMiddleTimeFF(max_len_ff, config.fps, ret_milliseconds=True,ff_frames=config.frames_per_block)


# Try aligning the platepar using FFT image registration
Expand All @@ -476,7 +476,7 @@ def _handleFailure(config, platepar, calstars_list, catalog_stars, _fft_refineme
min_radius = 10

# Prepare star dictionary to check the match
dt = FFfile.getMiddleTimeFF(max_len_ff, config.fps, ret_milliseconds=True)
dt = FFfile.getMiddleTimeFF(max_len_ff, config.fps, ret_milliseconds=True,ff_frames=config.frames_per_block)
jd = date2JD(*dt)
star_dict_temp = {}
star_dict_temp[jd] = calstars_dict[max_len_ff]
Expand Down
2 changes: 1 addition & 1 deletion RMS/Astrometry/FFTalign.py
Original file line number Diff line number Diff line change
Expand Up @@ -395,7 +395,7 @@ def alignPlatepar(config, platepar, calstars_time, calstars_coords, scale_update
calstars_coords[:, [0, 1]] = calstars_coords[:, [1, 0]]

# Get the time of the FF file
calstars_time = getMiddleTimeFF(max_len_ff, config.fps, ret_milliseconds=True)
calstars_time = getMiddleTimeFF(max_len_ff, config.fps, ret_milliseconds=True,ff_frames=config.frames_per_block)



Expand Down
16 changes: 9 additions & 7 deletions RMS/BufferedCapture.py
Original file line number Diff line number Diff line change
Expand Up @@ -285,16 +285,16 @@ def calculatePTSRegressionParams(self, y):
if self.b_error_debt > 0 or self.m_jump_error != 0:

# Don't limit changes to b for the first few blocks of frames
if x <= 256*3:
if x <= self.config.frames_per_block*3:
max_adjust = float('inf')

# Then adjust b aggressively for the first few minutes
elif x <= 256*6*10: # first ~10 min
max_adjust = 100*1000/256 # 0.1 ms per block
elif x <= self.config.frames_per_block*6*10: # first ~10 min
max_adjust = 100*1000/self.config.frames_per_block # 0.1 ms per block

# Then only allow small changes for the remainder of the run
else:
max_adjust = 25*1000/256 # 0.025 ms per block
max_adjust = 25*1000/self.config.frames_per_block # 0.025 ms per block

# Determine the correction factor
b_corr = min(self.b_error_debt, max_adjust) # ns
Expand Down Expand Up @@ -891,7 +891,7 @@ def run(self):


# Capture a block of 256 frames
block_frames = 256
block_frames = self.config.frames_per_block

log.info('Grabbing a new block of {:d} frames...'.format(block_frames))
for i in range(block_frames):
Expand Down Expand Up @@ -996,7 +996,7 @@ def run(self):
#gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

# Convert the frame to grayscale
if len(frame.shape) == 3:
if len(frame.shape) == 3 and not self.config.keep_color:

# If a color image is given, take the green channel
if frame.shape[2] == 3:
Expand All @@ -1010,7 +1010,9 @@ def run(self):
# Otherwise, take the first available channel
else:
gray = frame[:, :, 0]


# Add another dimension
gray = np.expand_dims(gray, axis=-1)
else:
gray = frame

Expand Down
6 changes: 3 additions & 3 deletions RMS/Compression.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,8 +133,8 @@ def saveFF(self, arr, startTime, N):
ff.nrows = arr.shape[1]
ff.ncols = arr.shape[2]
ff.nbits = self.config.bit_depth
ff.nframes = 256
ff.first = N + 256
ff.nframes = self.config.frames_per_block
ff.first = N + self.config.frames_per_block
ff.camno = self.config.stationID
ff.fps = self.config.fps
ff.starttime = date_string + "_" + str(micros).zfill(6)
Expand Down Expand Up @@ -301,7 +301,7 @@ def run(self):
t = time.time()

# Save the compressed image
filename_millis, filename_micros = self.saveFF(compressed, startTime, n*256)
filename_millis, filename_micros = self.saveFF(compressed, startTime, n*self.config.frames_per_block)
n += 1

log.debug("Saving time: {:.3f} s".format(time.time() - t))
Expand Down
157 changes: 157 additions & 0 deletions RMS/CompressionCy.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -174,4 +174,161 @@ def compressFrames(np.ndarray[INT8_TYPE_t, ndim=3] frames, int deinterlace_order
ftp_array[3, y, x] = var


return ftp_array, fieldsum[:frames_num*deinterlace_multiplier]

@cython.cdivision(True)
@cython.boundscheck(False)
@cython.wraparound(False)
def compressFrames(np.ndarray[INT8_TYPE_t, ndim=4] frames, int deinterlace_order):

# Init the output four frame temporal pixel array
cdef np.ndarray[INT8_TYPE_t, ndim=4] ftp_array = np.empty([4, frames.shape[1], frames.shape[2], frames.shape[3]],
dtype=INT8_TYPE)


# Array for field/frame intensity sums. If the video is interlaced, then there with will twice the number
# of fields as there are frames
cdef np.ndarray[INT32_TYPE_t, ndim=1] fieldsum = np.zeros((2*frames.shape[0]), INT32_TYPE)

cdef unsigned int deinterlace_multiplier = 2

# Init the field intensity sums array
if deinterlace_order < 0:

# If there's no deinterlacing, then only the values from the whole frame will be summed up
deinterlace_multiplier = 1

else:

# Otherwise, values from every field will be summed up
deinterlace_multiplier = 2


cdef unsigned short rand_count = 1

cdef unsigned int var, max_val, max_val_2, max_val_3, max_val_4, max_frame, mean, pixel, n, num_equal

cdef unsigned int x, y, acc
cdef unsigned int height = frames.shape[1]
cdef unsigned int width = frames.shape[2]
cdef unsigned int channel_num = frames.shape[3]
cdef unsigned int frames_num = frames.shape[0]
cdef unsigned int frames_num_minus_four = frames_num - 4
cdef unsigned int frames_num_minus_five = frames_num - 5

cdef unsigned int fieldsum_indx

# Populate the randomN array with 2**16 random numbers
cdef np.ndarray[INT8_TYPE_t, ndim=1] randomN = np.empty(shape=[65536], dtype=INT8_TYPE)
cdef unsigned int arand = randomN[0]


for n in range(65536):
arand = (arand*32719 + 3)%32749
randomN[n] = <unsigned char>(32767.0/<double>(1 + arand%32767))

for z in range(channel_num):
for y in range(height):
for x in range(width):

acc = 0
var = 0
max_val = 0
max_val_2 = 0
max_val_3 = 0
max_val_4 = 0
num_equal = 0

# Calculate mean, stddev, max_val, and max_val frame
for n in range(frames_num):

pixel = frames[n, y, x, z]
acc += pixel
var += pixel**2

# Assign the maximum value
if pixel > max_val:

# Track the top 4 maximum values
max_val_4 = max_val_3
max_val_3 = max_val_2
max_val_2 = max_val
max_val = pixel

max_frame = n
num_equal = 1


else:

# Randomize taken frame number for max_val pixel if there are several frames with the
# maximum value
if max_val == pixel:

num_equal += 1

# rand_count is unsigned short, which means it will overflow back to 0 after 65535
rand_count = (rand_count + 1)%65536

# Select the frame by random
if num_equal <= randomN[rand_count]:
max_frame = n


# Track the top 4 maximum values, which is used to remove wakes from mean and stddev
if pixel > max_val_2:
max_val_4 = max_val_3
max_val_3 = max_val_2
max_val_2 = pixel

elif pixel > max_val_3:
max_val_4 = max_val_3
max_val_3 = pixel

elif pixel > max_val_4:
max_val_4 = pixel


# Calculate the index for fieldsum, dependent on the deinterlace order (and if there's any
# detinerlacing at all)
fieldsum_indx = deinterlace_multiplier*n \
+ (deinterlace_multiplier - 1)*((y + deinterlace_order)%2)

# Sum intensity per every field
fieldsum[fieldsum_indx] += <unsigned long> pixel



# Calculate mean without top 4 max values
acc -= max_val + max_val_2 + max_val_3 + max_val_4
mean = acc/frames_num_minus_four




### Calculate stddev without top 4 max values ##

# Remove top 4 max values
var -= max_val**2 + max_val_2**2 + max_val_3**2 + max_val_4**2

# Subtract average squared sum of all values (acc*mean = acc*acc/frames_num_minus_four)
var -= acc*mean

# Compute the standard deviation
var = <unsigned int> sqrt(var/frames_num_minus_five)

# Make sure that the stddev is not 0, to prevent divide by zero afterwards
if var == 0:
var = 1

###


# Output results
ftp_array[0, y, x, z] = max_val
ftp_array[1, y, x, z] = max_frame
ftp_array[2, y, x, z] = mean
ftp_array[3, y, x, z] = var


return ftp_array, fieldsum[:frames_num*deinterlace_multiplier]
8 changes: 8 additions & 0 deletions RMS/ConfigReader.py
Original file line number Diff line number Diff line change
Expand Up @@ -263,12 +263,14 @@ def __init__(self):
# Media backend to use for capture. Options are gst, cv2, or v4l2
self.media_backend = "gst"
self.uyvy_pixelformat = False
self.keep_color=False

self.width = 1280
self.height = 720
self.width_device = self.width
self.height_device = self.height
self.fps = 25.0
self.frames_per_block=256

# Camera buffer in number of frames. This will applied a buffer/fps correction to
# the timestamps when in GStreamer Standalone mode
Expand Down Expand Up @@ -943,6 +945,9 @@ def parseCapture(config, parser):
if parser.has_option(section, "uyvy_pixelformat"):
config.uyvy_pixelformat = parser.getboolean(section, "uyvy_pixelformat")

if parser.has_option(section, "keep_color"):
config.keep_color = parser.getboolean(section, "keep_color")

if parser.has_option(section, "fps"):
config.fps = parser.getfloat(section, "fps")

Expand All @@ -952,6 +957,9 @@ def parseCapture(config, parser):
print()
print("WARNING! The FPS has been limited to 1,000,000!")

if parser.has_option(section, "frames_per_block"):
config.frames_per_block = parser.getint(section, "frames_per_block")

if parser.has_option(section, "camera_buffer"):
config.camera_buffer = parser.getint(section, "camera_buffer")

Expand Down
2 changes: 1 addition & 1 deletion RMS/DeleteOldObservations.py
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ def deleteOldObservations(data_dir, captured_dir, archived_dir, config, duration


# Calculate the approx. size for the night night
next_night_bytes = (duration*config.fps)/256*config.width*config.height*4
next_night_bytes = (duration*config.fps)/config.frames_per_block*config.width*config.height*4

# Always leave at least 2 GB free for archive
next_night_bytes += config.extra_space_gb*(1024**3)
Expand Down
6 changes: 4 additions & 2 deletions RMS/Detection.py
Original file line number Diff line number Diff line change
Expand Up @@ -387,7 +387,7 @@ def checkWhiteRatio(img_thres, ff, max_white_ratio):


def getLines(img_handle, k1, j1, time_slide, time_window_size, max_lines, max_white_ratio, kht_lib_path, \
mask=None, flat_struct=None, dark=None, debug=False):
mask=None, flat_struct=None, dark=None, debug=False, keep_color=False):
""" Get (rho, phi) pairs for each meteor present on the image using KHT.

Arguments:
Expand Down Expand Up @@ -515,6 +515,8 @@ def getLines(img_handle, k1, j1, time_slide, time_window_size, max_lines, max_wh
# 3 - close (Close surrounded pixels)
# 4 - thin (Thin all lines to 1px width)
# 1 - Remove lonely pixels
if keep_color:
img=np.dot(img[...,:3],[0.2989,0.5870,0.1140]).astype(np.uint8)
img = morph.morphApply(img, [1, 2, 3, 4, 1])


Expand Down Expand Up @@ -1106,7 +1108,7 @@ def detectMeteors(img_handle, config, flat_struct=None, dark=None, mask=None, as
# Get lines on the image
line_list = getLines(img_handle, config.k1_det, config.j1_det, config.time_slide, config.time_window_size,
config.max_lines_det, config.max_white_ratio, config.kht_lib_path, mask=mask, \
flat_struct=flat_struct, dark=dark, debug=debug)
flat_struct=flat_struct, dark=dark, debug=debug, keep_color=config.keep_color)

# logDebug('List of lines:', line_list)

Expand Down
2 changes: 1 addition & 1 deletion RMS/DetectionTools.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ def loadImageCalibration(dir_path, config, dtype=None, byteswap=False):
if dark_path is not None:

# Load the dark
dark = Image.loadDark(*os.path.split(dark_path), dtype=dtype, byteswap=byteswap)
dark = Image.loadDark(*os.path.split(dark_path), dtype=dtype, byteswap=byteswap, config=config.keep_color)

if dark is not None:
print('Loaded dark:', dark_path)
Expand Down
5 changes: 4 additions & 1 deletion RMS/ExtractStars.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,8 @@ def extractStars(ff_dir, ff_name, config=None, max_global_intensity=150, border=
return error_return

data = ff.avepixel.astype(np.float32)

if config.keep_color:
data=np.dot(data[...,:3],[0.2989,0.5870,0.1140]).astype(np.float32)

# Apply a mean filter to the image to reduce noise
data = ndimage.filters.convolve(data, weights=np.full((2, 2), 1.0/4))
Expand Down Expand Up @@ -291,6 +292,8 @@ def fitPSF(ff, avepixel_mean, x2, y2, config):

# Extract an image segment around each star
star_seg = ff.avepixel[y_min:y_max, x_min:x_max]
if config.keep_color:
star_seg=np.dot(star_seg[...,:3],[0.2989,0.5870,0.1140])

# Create x and y indices
y_ind, x_ind = np.indices(star_seg.shape)
Expand Down
Loading