From 9f1609ded4d36a60430fcae48e8c5e8598d5fe26 Mon Sep 17 00:00:00 2001 From: tpollina Date: Sun, 2 Feb 2020 04:20:55 +0100 Subject: [PATCH] Update mqtt_pump_focus_image.py --- scripts/mqtt_pump_focus_image.py | 234 ++++++++++++++++++++++--------- 1 file changed, 166 insertions(+), 68 deletions(-) diff --git a/scripts/mqtt_pump_focus_image.py b/scripts/mqtt_pump_focus_image.py index d0290d8..d2d3b81 100644 --- a/scripts/mqtt_pump_focus_image.py +++ b/scripts/mqtt_pump_focus_image.py @@ -4,11 +4,10 @@ from datetime import datetime, timedelta from adafruit_motor import stepper from adafruit_motorkit import MotorKit from time import sleep - -import shutil import json import os +import subprocess from skimage.util import img_as_ubyte @@ -25,16 +24,21 @@ from morphocut.image import ( RescaleIntensity, RGB2Gray, ) + from morphocut.stat import RunningMedian from morphocut.str import Format -from morphocut.stream import TQDM, Enumerate +from morphocut.stream import TQDM, Enumerate, FilterVariables from skimage.feature import canny from skimage.color import rgb2gray, label2rgb from skimage.morphology import disk from skimage.morphology import erosion, dilation, closing from skimage.measure import label, regionprops +import cv2, shutil +import smbus +#fan +bus = smbus.SMBus(1) ################################################################################ kit = MotorKit() pump_stepper = kit.stepper1 @@ -47,12 +51,8 @@ focus_stepper.release() camera = PiCamera() camera.resolution = (3280, 2464) camera.iso = 60 -sleep(3) camera.shutter_speed = 500 -camera.exposure_mode = 'off' -g = camera.awb_gains -camera.awb_mode = 'off' -camera.awb_gains = g +camera.exposure_mode = 'fixedfps' ################################################################################ message = '' @@ -62,9 +62,9 @@ count='' ################################################################################ def on_connect(client, userdata, flags, rc): - print("Connected! - " + str(rc)) - client.subscribe("actuator/#") - + print("Connected! - " + str(rc)) + client.subscribe("actuator/#") + rgb(0,255,0) def on_subscribe(client, obj, mid, granted_qos): print("Subscribed! - "+str(mid)+" "+str(granted_qos)) @@ -80,6 +80,24 @@ def on_message(client, userdata, msg): def on_log(client, obj, level, string): print(string) +def rgb(R,G,B): + bus.write_byte_data(0x0d, 0x00, 0) + bus.write_byte_data(0x0d, 0x01, R) + bus.write_byte_data(0x0d, 0x02, G) + bus.write_byte_data(0x0d, 0x03, B) + + bus.write_byte_data(0x0d, 0x00, 1) + bus.write_byte_data(0x0d, 0x01, R) + bus.write_byte_data(0x0d, 0x02, G) + bus.write_byte_data(0x0d, 0x03, B) + + bus.write_byte_data(0x0d, 0x00, 2) + bus.write_byte_data(0x0d, 0x01, R) + bus.write_byte_data(0x0d, 0x02, G) + bus.write_byte_data(0x0d, 0x03, B) + cmd="i2cdetect -y 1" + subprocess.Popen(cmd.split(),stdout=subprocess.PIPE) + ################################################################################ client = mqtt.Client() client.connect("127.0.0.1",1883,60) @@ -94,22 +112,23 @@ client.loop_start() while True: ################################################################################ - if (topic=="pump"): - + if (topic=="pump"): + rgb(0,0,255) direction=message.split(" ")[0] delay=float(message.split(" ")[1]) nb_step=int(message.split(" ")[2]) client.publish("receiver/pump", "Start"); - if direction == "BACKWARD": - direction=stepper.direction - if direction == "FORWARD": - direction=stepper.FORWARD while True: + + if direction == "BACKWARD": + direction=stepper.BACKWARD + if direction == "FORWARD": + direction=stepper.FORWARD count+=1 - print(count,nb_step) +# print(count,nb_step) pump_stepper.onestep(direction=direction, style=stepper.DOUBLE) sleep(delay) @@ -117,6 +136,7 @@ while True: pump_stepper.release() print("The pump has been interrompted.") client.publish("receiver/pump", "Interrompted"); + rgb(0,255,0) break if count>nb_step: @@ -124,31 +144,34 @@ while True: print("The pumping is done.") topic="wait" client.publish("receiver/pump", "Done"); + rgb(0,255,0) break ################################################################################ elif (topic=="focus"): + rgb(255,255,0) direction=message.split(" ")[0] nb_step=int(message.split(" ")[1]) client.publish("receiver/focus", "Start"); - if direction == "FORWARD": - direction=stepper.FORWARD - if direction == "BACKWARD": - direction=stepper.BACKWARD while True: - count+=1 - print(count,nb_step) - focus_stepper.onestep(direction=direction, style=stepper.MICROSTEP) + if direction == "FORWARD": + direction=stepper.FORWARD + if direction == "BACKWARD": + direction=stepper.BACKWARD + count+=1 +# print(count,nb_step) + focus_stepper.onestep(direction=direction, style=stepper.MICROSTEP) if topic!="focus": focus_stepper.release() print("The stage has been interrompted.") client.publish("receiver/focus", "Interrompted"); + rgb(0,255,0) break if count>nb_step: @@ -156,12 +179,15 @@ while True: print("The focusing is done.") topic="wait" client.publish("receiver/focus", "Done"); + rgb(0,255,0) break ################################################################################ elif (topic=="image"): + camera.start_preview(fullscreen=False, window = (160, 0, 640, 480)) + sleep_before=int(message.split(" ")[0]) nb_step=int(message.split(" ")[1]) @@ -179,37 +205,51 @@ while True: #flushing before to begin + rgb(0,0,255) for i in range(nb_step): pump_stepper.onestep(direction=stepper.FORWARD, style=stepper.DOUBLE) - sleep(0.01) + sleep(0.01) + rgb(0,255,0) + directory = os.path.join(path, "PlanktonScope") os.makedirs(directory, exist_ok=True) + export = os.path.join(directory, "export") + os.makedirs(export, exist_ok=True) + date=datetime.now().strftime("%m_%d_%Y") time=datetime.now().strftime("%H_%M") path_date = os.path.join(directory, date) os.makedirs(path_date, exist_ok=True) - path_time = os.path.join(path_date,time) - os.makedirs(path_time, exist_ok=True) while True: count+=1 - print(count,nb_frame) +# print(count,nb_frame) filename = os.path.join(path_time,datetime.now().strftime("%M_%S_%f")+".jpg") + + rgb(0,255,255) camera.capture(filename) - client.publish("receiver/image", datetime.now().strftime("%M_%S_%f")+".jpg has been imaged."); + rgb(0,255,0) + client.publish("receiver/image", datetime.now().strftime("%M_%S_%f")+".jpg has been imaged."); + + rgb(0,0,255) for i in range(10): pump_stepper.onestep(direction=stepper.FORWARD, style=stepper.DOUBLE) sleep(0.01) sleep(0.5) + rgb(0,255,0) if(count>nb_frame): + + camera.stop_preview() + + client.publish("receiver/image", "Completed"); # Meta data that is added to every object local_metadata = { "process_datetime": datetime.now(), @@ -217,106 +257,154 @@ while True: "acq_camera_iso" : camera.iso, "acq_camera_shutter_speed" : camera.shutter_speed } - + global_metadata = None + config_txt = None + RAW = None + CLEAN = None + ANNOTATED = None + OBJECTS = None + archive_fn = None + config_txt = open('/home/pi/PlanktonScope/config.txt','r') node_red_metadata = json.loads(config_txt.read()) global_metadata = {**local_metadata, **node_red_metadata} + + RAW = os.path.join(path_time, "RAW") + os.makedirs(RAW, exist_ok=True) + + os.system("mv "+str(path_time)+"/*.jpg "+str(RAW)) - import_path = path_time - archive_fn = os.path.join(directory, str(date)+"_"+str(time)+"_ecotaxa_export.zip") + CLEAN = os.path.join(path_time, "CLEAN") + os.makedirs(CLEAN, exist_ok=True) + + ANNOTATED = os.path.join(path_time, "ANNOTATED") + os.makedirs(ANNOTATED, exist_ok=True) + OBJECTS = os.path.join(path_time, "OBJECTS") + os.makedirs(OBJECTS, exist_ok=True) + + archive_fn = os.path.join(directory,"export", str(date)+"_"+str(time)+"_ecotaxa_export.zip") + + client.publish("receiver/segmentation", "Start"); # Define processing pipeline + # Define processing pipeline with Pipeline() as p: # Recursively find .jpg files in import_path. # Sort to get consective frames. - abs_path = Find(import_path, [".jpg"], sort=True, verbose=True) + abs_path = Find(RAW, [".jpg"], sort=True, verbose=True) + + FilterVariables(abs_path) # Extract name from abs_path name = Call(lambda p: os.path.splitext(os.path.basename(p))[0], abs_path) + Call(rgb, 0,255,0) # Read image img = ImageReader(abs_path) + # Show progress bar for frames + #TQDM(Format("Frame {name}", name=name)) + # Apply running median to approximate the background image flat_field = RunningMedian(img, 5) - + # Correct image img = img / flat_field + FilterVariables(name,img) + # Rescale intensities and convert to uint8 to speed up calculations img = RescaleIntensity(img, in_range=(0, 1.1), dtype="uint8") - + + frame_fn = Format(os.path.join(CLEAN, "{name}.jpg"), name=name) + + ImageWriter(frame_fn, img) + + FilterVariables(name,img) + # Convert image to uint8 gray img_gray = RGB2Gray(img) - + + # ? img_gray = Call(img_as_ubyte, img_gray) - img_canny = Call(canny, img_gray, sigma=0.3) + #Canny edge detection + img_canny = Call(cv2.Canny, img_gray, 50,100) - img_dilate = Call(dilation, img_canny) - - img_closing = Call(closing, img_dilate) - - mask = Call(erosion, img_closing) - - # Show progress bar for frames - TQDM(Format("Frame {name}", name=name)) + #Dilate + kernel = Call(cv2.getStructuringElement, cv2.MORPH_ELLIPSE, (15, 15)) + img_dilate = Call(cv2.dilate, img_canny, kernel, iterations=2) + + #Close + kernel = Call(cv2.getStructuringElement, cv2.MORPH_ELLIPSE, (5, 5)) + img_close = Call(cv2.morphologyEx, img_dilate, cv2.MORPH_CLOSE, kernel, iterations=1) + + #Erode + kernel = Call(cv2.getStructuringElement, cv2.MORPH_ELLIPSE, (15, 15)) + mask = Call(cv2.erode, img_close, kernel, iterations=2) + + FilterVariables(name,img,img_gray,mask) - # Apply threshold find objects - #threshold = 204 # Call(skimage.filters.threshold_otsu, img_gray) - #mask = img_gray < threshold - # Find objects regionprops = FindRegions( mask, img_gray, min_area=1000, padding=10, warn_empty=name ) - + + Call(rgb, 255,0,255) # For an object, extract a vignette/ROI from the image roi_orig = ExtractROI(img, regionprops, bg_color=255) - roi_orig # Generate an object identifier i = Enumerate() #Call(print,i) object_id = Format("{name}_{i:d}", name=name, i=i) #Call(print,object_id) - + + object_fn = Format(os.path.join(OBJECTS, "{name}.jpg"), name=object_id) + + ImageWriter(object_fn, roi_orig) # Calculate features. The calculated features are added to the global_metadata. # Returns a Variable representing a dict for every object in the stream. meta = CalculateZooProcessFeatures( regionprops, prefix="object_", meta=global_metadata ) - # If CalculateZooProcessFeatures is not used, we need to copy global_metadata into the stream: - # meta = Call(lambda: global_metadata.copy()) - # https://github.com/morphocut/morphocut/issues/51 - + json_meta = Call(json.dumps,meta, sort_keys=True, default=str) + + Call(client.publish, "receiver/segmentation/metric", json_meta) + # Add object_id to the metadata dictionary meta["object_id"] = object_id # Generate object filenames orig_fn = Format("{object_id}.jpg", object_id=object_id) + FilterVariables(orig_fn,roi_orig,meta,object_id) # Write objects to an EcoTaxa archive: # roi image in original color, roi image in grayscale, metadata associated with each object EcotaxaWriter(archive_fn, (orig_fn, roi_orig), meta) # Progress bar for objects TQDM(Format("Object {object_id}", object_id=object_id)) + + Call(client.publish, "receiver/segmentation/object_id", object_id) + + meta=None + FilterVariables(meta) - Call(client.publish, "receiver/image", object_id) p.run() - #remove directory - shutil.rmtree(import_path) - sleep(sleep_during) - for i in range(nb_step): - pump_stepper.onestep(direction=stepper.FORWARD, style=stepper.DOUBLE) - sleep(0.01) - count=0 + #remove directory + #shutil.rmtree(import_path) + + client.publish("receiver/segmentation", "Completed"); + + rgb(255,255,255) + sleep(sleep_during) + rgb(0,255,0) date=datetime.now().strftime("%m_%d_%Y") time=datetime.now().strftime("%H_%M") @@ -324,18 +412,28 @@ while True: path_date = os.path.join(directory, date) os.makedirs(path_date, exist_ok=True) - path_time = os.path.join(path_date,time) + os.makedirs(path_time, exist_ok=True) + + rgb(0,0,255) + for i in range(nb_step): + pump_stepper.onestep(direction=stepper.FORWARD, style=stepper.DOUBLE) + sleep(0.01) + rgb(0,255,0) os.makedirs(path_time, exist_ok=True) + count=0 + if topic!="image": - pump_focus.release() + pump_stepper.release() print("The imaging has been interrompted.") client.publish("receiver/image", "Interrompted"); + rgb(0,255,0) + count=0 break else: - print("Waiting") +# print("Waiting") sleep(1)