Skip to content
Open
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
35 changes: 13 additions & 22 deletions software/SAT0_OBC/SatImageTaking/star_finder.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,18 +55,18 @@ class star_finder:
gray_image (np.ndarray): The grayscale version of the original image.
sensitivity (int): Sensitivity of the threshold used when finding stars.
mask (np.ndarray): The mask used to find stars.
stars (list): A list of detected stars, including center, radius, and brightness.
stars (list): A list of detected stars, including thier image, center(x,y), radius, and brightness.
N_stars (int): The number of stars to detect.

Methods:
find_stars(): Finds stars in the image and stores them in the 'stars' attribute.
extract_star(): Extracts a single star from the image.
get_threshold(): Returns the threshold used to find stars.
get_brightness(): Returns the brightness of a star.
draw (): draw the stars on the image.
"""

def __init__(self, path_or_image: str or list, gray_image=0, sensitivity=100, N_stars=None, dim=None, draw=False,) -> None:
# 19.9.2023 asaf h: lowered the default sensitivity for better result
def __init__(self, path_or_image: str or list, gray_image=0, sensitivity=50, N_stars=None, dim=None, draw=False,) -> None:
"""
Initializes the star_finder object.
"""
Expand Down Expand Up @@ -110,11 +110,18 @@ def find_stars(self):
center = x, y
if r == 0:
r = 1
r += 1
star = self.extract_star(y, x, r)
stars_data.append(
(star, center, r, star_finder.get_brightness(star)))
# 19.9.2023 asaf h: removed my get_brightness function for: brightest_pixal = np.amax(star)
brightest_pixal = np.amax(star)
# 19.9.2023 asaf h: filter out all the stars that dont not meet the minimum thresholdץ
if brightest_pixal < self.sensitivity:
continue

stars_data.sort(key=lambda cnt: cnt[2], reverse=True)
stars_data.append(
(star, center, r, brightest_pixal))
# 19.9.2023 asaf h: sort by brightest_pixal
stars_data.sort(key=lambda cnt: cnt[3], reverse=True)
return stars_data

def extract_star(self, y, x, r):
Expand Down Expand Up @@ -151,22 +158,6 @@ def get_threshold(self):
gray_image, 255, ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY_INV, blockSize=5, C=1)
return adaptive_mean

@staticmethod
def get_brightness(star):
"""
Calculates the brightness of a star.

Args:
star (np.ndarray): Cropped star.

Returns:
int: Brightness of the star.
"""
brightest_pixal = np.amax(star)
p = 0.1
threshold_pixal = brightest_pixal - brightest_pixal * p * 3
return np.sum(star[star > threshold_pixal])

def draw(self):
"""
Draws the stars on the image.
Expand Down
106 changes: 43 additions & 63 deletions software/SAT0_OBC/SatImageTaking/start_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ def main(outputFolder: str, parameters_list: list) -> None:
3: makeIcon (img_path, width, height, quality_factor, gray) will create an icon out of a given image path with
custom parameters.

4: StarAnalysisOnPhotosThatAlreadyBeTaken (mission_count, width, height, sensitive, n_stars, with_mask) will run star analysis
4: StarAnalysis (mission_count, width, height, sensitive, n_stars, with_mask) will run star analysis
on photos that have already been taken with given a custom parameters.

5: testingOnPreSavedImages (missionID, x, y, quality_factor, gray, vga, img_n) will be able to run the above functions
Expand Down Expand Up @@ -149,7 +149,8 @@ def main(outputFolder: str, parameters_list: list) -> None:
img_n = parameters_list[9] if len(parameters_list) > 9 else 0

mission = mission_Table[missionType]
mission(x, y, quality_factor, gray, vga, img_n)
# 19.9.2023 asaf h: missionID was missing, it is like missionType, 7 arguments are needed for testing
mission(missionID, x, y, quality_factor, gray, vga, img_n)


def TakePhotoStarAnalysis(quality: int, width: int, height: int, Shutter: int, ISO: int) -> None:
Expand All @@ -167,13 +168,7 @@ def TakePhotoStarAnalysis(quality: int, width: int, height: int, Shutter: int, I
None
"""
print("Started TakePhotoStarAnalysis")
if width == 0:
width = 640
if height == 0:
height = 480
if quality == 0:
quality = 10

# 19.9.2023 asaf h: there is no need to define the parameters, takePictureWithParameters does that.
img = takePictureWithParameters(quality, width, height, Shutter, ISO)

# define Dimensions
Expand All @@ -193,8 +188,8 @@ def TakePhotoStarAnalysis(quality: int, width: int, height: int, Shutter: int, I
print("Starting writeMetaDataStars")
writeMetaDataStars(stars_list)


def StarAnalysis(mission_count: int, width=1280, height=720, sensitive=100, n_stars=30, without_earth_mask=0):
# 19.9.2023 asaf h: the default numbers needs to be removed cuz 0 is sent not None, they will be difined later
def StarAnalysis(mission_count: int, width: int, height: int, sensitive: int, n_stars: int, without_earth_mask=0):
"""Analyzes an image to identify stars

Args:
Expand All @@ -209,12 +204,13 @@ def StarAnalysis(mission_count: int, width=1280, height=720, sensitive=100, n_st
stars_list (list): A list of the detected stars in the image
"""
print("Started StarAnalysis")
# 19.9.2023 asaf h: fixed the default numbers
if width == 0:
width = 640
width = 1280
if height == 0:
height = 480
height = 720
if sensitive == 0:
sensitive = 100
sensitive = 50
if n_stars == 0:
n_stars = 30

Expand All @@ -227,7 +223,8 @@ def StarAnalysis(mission_count: int, width=1280, height=720, sensitive=100, n_st

# star detection
detected_object = findStarsNoDarkEarth(img, img_object, sensitive, n_stars)
detected_object.draw()
# 19.9.2023 asaf h: detected_object.draw() and saveFinalImg(detected_object.draw_image, "Detected")
# will save the image with the green circels on the stars on the pi for future analysis. its unnecessary.

# get stars list:
stars_list = get_stars(detected_object)
Expand All @@ -236,34 +233,17 @@ def StarAnalysis(mission_count: int, width=1280, height=720, sensitive=100, n_st
print("Starting writeMetaDataStars")
writeMetaDataStars(stars_list)
print("Starting saveFinalImg")
saveFinalImg(detected_object.draw_image, "Detected")


def takeStandardPicture() -> np.ndarray:
"""Takes a standard picture with default raspistill image capture parameters.
The picture is taken by a cmd function

Returns:
img (np.ndarray): A numpy array containing the image
"""

print("Started takeStandardPicture")
comm = f"raspistill -o {output}/Img.jpeg"
print(comm)
os.system(comm)
read = f"{output}/Img.jpeg"
print(read)
img = cv2_imread(read)
return img

# 19.9.2023 asaf h: removed takeStandardPicture function cuz there is no need to. check line 268 (else)

# 19.9.2023 asaf h: fixed the main function takePictureWithParameters. rony please double check it again. it should be fine
def takePictureWithParameters(quality: int, width: int, height: int, Shutter: int, ISO: int) -> np.ndarray:
"""Take a picture with specified parameters

Args:
quality (int): The quality of the image (default 10)
width (int): The width of the image (default 640)
height (int): The height of the image (default 480)
quality (int): The quality of the image (default 100)
width (int): The width of the image (default 1280)
height (int): The height of the image (default 720)
Shutter (int): The shutter speed of the camera (default 0)
ISO (int): The ISO of the camera (default 0)

Expand All @@ -273,35 +253,26 @@ def takePictureWithParameters(quality: int, width: int, height: int, Shutter: in

print("Started takePictureWithParameters")
if quality == 0:
quality = 10
quality = 100
if width == 0:
width = 640
width = 1280
if height == 0:
height = 480
height = 720

if (quality != 100 and width != 1280 and height != 720 and Shutter != 0 and ISO != 0):
if (Shutter != 0 and ISO != 0):
command_with_parameters = f"raspistill -o {output}/Img.jpeg --quality {quality} --width {width} --height {height} --shutter {Shutter} --ISO {ISO} -th none"
os.system(command_with_parameters)
read = f"{output}/Img.jpeg"
img = cv2_imread(read)
elif (quality != 100 and width != 1280 and height != 720 and Shutter != 0):
elif (Shutter != 0):
command_with_parameters = f"raspistill -o {output}/Img.jpeg --quality {quality} --width {width} --height {height} --shutter {Shutter} -th none"
os.system(command_with_parameters)
read = f"{output}/Img.jpeg"
img = cv2_imread(read)
elif (quality != 100 and width != 1280 and height != 720):
command_with_parameters = f"raspistill -o {output}/Img.jpeg --quality {quality} --width {width} --height {height} -th none"
os.system(command_with_parameters)
read = f"{output}/Img.jpeg"
img = cv2_imread(read)
elif (quality != 100):
command_with_parameters = f"raspistill -o {output}/Img.jpeg --quality {quality} -th none"
os.system(command_with_parameters)
read = f"{output}/Img.jpeg"
img = cv2_imread(read)
elif (ISO != 0):
command_with_parameters = f"raspistill -o {output}/Img.jpeg --quality {quality} --width {width} --height {height} --ISO {ISO} -th none"
else:
img = takeStandardPicture()
read = f"{output}/Img.jpeg"
command_with_parameters = f"raspistill -o {output}/Img.jpeg --quality {quality} --width {width} --height {height} -th none"

# 19.9.2023 asaf h: removed the take standard picture. unnecessary function

os.system(command_with_parameters)
read = f"{output}/Img.jpeg"
img = cv2_imread(read)

print("Compressing")
CompressImage(img, output, save_full=True)
Expand All @@ -313,8 +284,8 @@ def takePictureWithParameters(quality: int, width: int, height: int, Shutter: in
writeMetaDataSmallImg(read, isGoodImage)
return img


def findStarsNoDarkEarth(img: np.ndarray, img_object: np.ndarray, sensitive=100, n_stars=30) -> np.ndarray:
# 19.9.2023 asaf h: lower the default sensitive for better result
def findStarsNoDarkEarth(img: np.ndarray, img_object: np.ndarray, sensitive=50, n_stars=30) -> np.ndarray:
"""Finds stars in an image while the Earth is lit and not dark

Args:
Expand Down Expand Up @@ -517,7 +488,16 @@ def testing(missionType: int, x: int, y: int, quality_factor: int, gray: bool, q
"""
img_path = f"SatImageTaking/photos{img_n}.jpeg"
mission = mission_Table[missionType]
mission(img_path, x, y, quality_factor, gray, qvga)
# 19.9.2023 asaf h: each function has its own order
if mission == makeIcon: #
mission(img_path, x, y, quality_factor, gray)
elif mission == crop_and_compress:
mission(img_path, x, y, quality_factor, gray, qvga)
else: #StarAnalysis
sensitive = quality_factor
n_stars = gray
without_earth_mask = qvga
mission(img_path, x, y, sensitive, n_stars, without_earth_mask)


def CompressImage(in_img: np.ndarray, path: str, max_size: int = 16 * LIT.KBYTE, comp_gray=True, save_full=False) -> str and np.ndarray:
Expand Down
3 changes: 2 additions & 1 deletion software/SAT0_OBC/SatImageTaking/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,8 @@ def get_pic_path_list(path: str) -> list:
list: List of path of images in the directory.
"""
file_list = os.listdir(path)
pic_path_list = [path + i for i in file_list if i.endswith(('.png', '.jpg', '.jpeg', '.jfif')) and
# 19.9.2023 asaf h: fix bug
pic_path_list = [path + '/' + i for i in file_list if i.endswith(('.png', '.jpg', '.jpeg', '.jfif')) and
not i.startswith('.')]
return pic_path_list

Expand Down
14 changes: 7 additions & 7 deletions software/SAT0_OBC/controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ def msgArrived(self, msgByte):

elif command == CmdTypes.CMD_UPLOAD_FILE.value: # 16
print("*** CmdTypes.CMD_UPLOAD_FILE ***")

# set state to in mission and sendmsg
self.state = StateTypes.STATE_BUSY.value
self.serial.sendMsg(bytearray([ApiTypes.API_ACK.value]))
Expand All @@ -273,18 +273,18 @@ def msgArrived(self, msgByte):
scriptNum = paramsList[1]
line_num = paramsList[2]
num_chars = paramsList[3]

add = lambda i: chr(int(hex(i), 16))
txt = ''.join([add(i) for i in paramsList[4: 4 + num_chars]])

reset = 1 if len(paramsList[: 4 + num_chars]) < len(paramsList) and paramsList[-1] != 0 else 0 #TODO how to reset
# 19.9.2023 asaf h: To reset the file it is better to send 1 instead of not 0.
reset = 1 if len(paramsList[: 4 + num_chars]) < len(paramsList) and paramsList[-1] == 1 else 0
# execute mission with parameters:
print('parms: * > * > ' , f'missionCount: {missionCount}, scriptNum: {scriptNum}, ', end='')
print('parms: * > * > ' , f'missionCount: {missionCount}, scriptNum: {scriptNum}, ', end='')
print(f'line_num: {line_num}, num_chars: {num_chars}, txt: {repr(txt)}, reset: {reset}')

import uploading
uploading.main(missionCount, scriptNum, line_num, txt, reset)

# finished executing mission:
self.state = StateTypes.STATE_READY.value
print("*** CmdTypes.CMD_UPLOAD_FILE Done ***")
Expand Down
Loading