Last active
August 8, 2018 15:16
-
-
Save delattj/52a8e42bfd023af4b09789d90df99989 to your computer and use it in GitHub Desktop.
Capture RGB with Dither (SharpCap 3.0)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# ________________________________________Capture RGB with Dither_________________________________________ | |
import os | |
import clr | |
import time | |
import subprocess | |
clr.AddReference("SharpCap") | |
clr.AddReference('System.Windows.Forms') | |
clr.AddReference('System.Drawing') | |
from SharpCap.UI import CaptureLimitType | |
from System.Windows.Forms import * # Windows UI | |
from System.Drawing import Point, Color, Font, FontStyle, Size | |
from System.Environment import GetFolderPath, SpecialFolder | |
from System.Threading import Thread | |
dither_cmd = r"C:\Program Files (x86)\MetaGuide\MGDither.exe" | |
desktop_folder = GetFolderPath(SpecialFolder.Desktop) | |
wait_precision = 0.01 # In second | |
def capture_RVB_dither( | |
Name="Cible", | |
Gain=300, # gain | |
Expo=5, # temps exposition par pose | |
Dither=True, # dither | |
Frames=1, # nombre de poses | |
Count=1, # nombre de sequences | |
Wait=3, # attente pour stabilisation apres Dithering | |
Output=desktop_folder, | |
dialog=None | |
): | |
if not Dither: | |
Wait = 3 | |
def wait(second): | |
if dialog: | |
return dialog.wait_abord(second) | |
else: | |
Thread.Sleep(int(second*1000)) | |
def wait_call(cmds): | |
if dialog: | |
call = subprocess.Popen(cmds) | |
return dialog.wait_call_abord(call) | |
else: | |
subprocess.call(cmds) | |
def log(text): | |
if dialog: | |
dialog.process.log(text) | |
else: | |
print text | |
def log_error(text): | |
if dialog: | |
dialog.process.log_error(text) | |
else: | |
print text | |
log("Start Capture") | |
log("Nom: %s"% Name) | |
log("Gain: %d"% Gain) | |
log("Temps d'exposition: %.2f secondes"% Expo) | |
log("Nombre de poses: %d"% Frames) | |
log("Nombre de sequences: %d"% Count) | |
log("Output: %s"% Output) | |
try: | |
if wait(1): return | |
# __set folder format | |
SharpCap.SelectedCamera.Controls.OutputFormat.Value = "Fits files (*.fits)" | |
SharpCap.TargetName = Name | |
# __set camera | |
SharpCap.SelectedCamera.Controls.Exposure.Value = Expo | |
SharpCap.SelectedCamera.Controls.Gain.Value = Gain | |
# _____________________________________Capture sequence RVB dither__________________________________________________ | |
for i in range(Count): | |
# __set filter Red | |
if Dither and wait_call([dither_cmd]): return | |
SharpCap.Wheels.SelectedWheel.Position = 2 | |
SharpCap.CaptureFolder = os.path.join(Output, "Capture Red") | |
if wait(Expo+Wait): return | |
# _______print compte à rebours sequence | |
log("Sequences Red: %d / %d"% (i+1, Count)) | |
# _________setup capture Red (limited , count, wait) | |
SharpCap.SelectedCamera.CaptureConfig.CaptureLimitType = CaptureLimitType.FrameLimited | |
SharpCap.SelectedCamera.CaptureConfig.CaptureLimitValue = Frames | |
SharpCap.SelectedCamera.CaptureConfig.CaptureSequenceCount = 1 | |
SharpCap.SelectedCamera.CaptureConfig.CaptureSequenceInterval = 0 | |
# _________start capture Red | |
SharpCap.SelectedCamera.PrepareToCapture() | |
SharpCap.SelectedCamera.RunCapture() | |
if wait((Expo+0.25)*Frames): return | |
# __set filter Green | |
if Dither and wait_call([dither_cmd]): return | |
SharpCap.Wheels.SelectedWheel.Position = 3 | |
SharpCap.CaptureFolder = os.path.join(Output, "Capture Green") | |
if wait(Expo+Wait): return | |
# _______print compte à rebours sequence | |
log("Sequences Green: %d / %d"% (i+1, Count)) | |
# ________setup capture Green (limited , count, wait) | |
SharpCap.SelectedCamera.CaptureConfig.CaptureLimitType = CaptureLimitType.FrameLimited | |
SharpCap.SelectedCamera.CaptureConfig.CaptureLimitValue = Frames | |
SharpCap.SelectedCamera.CaptureConfig.CaptureSequenceCount = 1 | |
SharpCap.SelectedCamera.CaptureConfig.CaptureSequenceInterval = 0 | |
# ________start capture Green | |
SharpCap.SelectedCamera.PrepareToCapture() | |
SharpCap.SelectedCamera.RunCapture() | |
if wait((Expo+0.25)*Frames): return | |
# __set filter Blue | |
if Dither and wait_call([dither_cmd]): return | |
SharpCap.Wheels.SelectedWheel.Position = 4 | |
SharpCap.CaptureFolder = os.path.join(Output, "Capture Blue") | |
if wait(Expo+Wait): return | |
# _______print compte à rebours sequence | |
log("Sequences Blue: %d / %d"% (i+1, Count)) | |
# _______setup capture Blue (limited , count, wait) | |
SharpCap.SelectedCamera.CaptureConfig.CaptureLimitType = CaptureLimitType.FrameLimited | |
SharpCap.SelectedCamera.CaptureConfig.CaptureLimitValue = Frames | |
SharpCap.SelectedCamera.CaptureConfig.CaptureSequenceCount = 1 | |
SharpCap.SelectedCamera.CaptureConfig.CaptureSequenceInterval = 0 | |
# _______start capture Blue | |
SharpCap.SelectedCamera.PrepareToCapture() | |
SharpCap.SelectedCamera.RunCapture() | |
if wait((Expo+0.25)*Frames): return | |
except: | |
import traceback | |
log_error(traceback.format_exc()) | |
finally: | |
if dialog: | |
dialog.end_capture() | |
log("End Capture") | |
class ValueInput(Panel): | |
def __init__(self, label, default_value=""): | |
super(ValueInput, self).__init__() | |
self.Height = 30 | |
self.default_value = default_value | |
label_widget = Label() | |
label_widget.Text = label +":" | |
label_widget.Dock = DockStyle.Right | |
label_widget.AutoSize = True | |
label_widget.Padding = Padding(2) | |
input_widget = TextBox() | |
input_widget.Text = str(default_value) | |
input_widget.Dock = DockStyle.Right | |
self.Controls.Add(label_widget) | |
self.Controls.Add(input_widget) | |
self.label = label_widget | |
self.input = input_widget | |
def resize_to_contents(self): | |
self.Width = self.label.Width + self.input.Width | |
def get_label(self): | |
return self.label.Text[:-1] | |
def get_value(self): | |
return self.input.Text | |
def get_value_as_int(self): | |
return int(self.input.Text) | |
def get_value_as_float(self): | |
return float(self.input.Text) | |
class FolderPicker(FlowLayoutPanel): | |
def __init__(self, label, default_value=""): | |
super(FolderPicker, self).__init__() | |
self.Height = 30 | |
self.WrapContents = False | |
self.default_value = default_value | |
label_widget = Label() | |
label_widget.Text = label +":" | |
# label_widget.Dock = DockStyle.Right | |
label_widget.AutoSize = True | |
label_widget.Padding = Padding(5) | |
input_widget = TextBox() | |
input_widget.Text = str(default_value) | |
input_widget.Dock = DockStyle.Right | |
browse = Button() | |
browse.Text = "Browse" | |
# browse.Height = 10 | |
# browse.Dock = DockStyle.Right | |
browse.Click += self.get_picked_folder | |
# browse.AutoSize = True | |
self.Controls.Add(label_widget) | |
self.Controls.Add(input_widget) | |
self.Controls.Add(browse) | |
self.label = label_widget | |
self.input = input_widget | |
self.browse = browse | |
def resize_to_contents(self): | |
self.Width = self.label.Width + self.input.Width + self.browse.Width + 30 | |
pass | |
def get_label(self): | |
return self.label.Text[:-1] | |
def get_value(self): | |
return self.input.Text | |
def get_picked_folder(self, *args): | |
folder_picker = FolderBrowserDialog() | |
folder_picker.Description = "Pick a target Folder" | |
if self.input.Text != "": | |
folder_picker.SelectedPath = self.input.Text | |
if folder_picker.ShowDialog(): | |
self.input.Text = folder_picker.SelectedPath | |
class LabeledCheckBox(Panel): | |
def __init__(self, label, default_value=True): | |
super(LabeledCheckBox, self).__init__() | |
self.Height = 30 | |
self.default_value = default_value | |
label_widget = Label() | |
label_widget.Text = label +":" | |
label_widget.Dock = DockStyle.Right | |
label_widget.AutoSize = True | |
label_widget.Padding = Padding(7) | |
input_widget = CheckBox() | |
input_widget.Checked = default_value | |
input_widget.Dock = DockStyle.Right | |
input_widget.AutoSize = True | |
self.Controls.Add(label_widget) | |
self.Controls.Add(input_widget) | |
self.label = label_widget | |
self.input = input_widget | |
def resize_to_contents(self): | |
self.Width = self.label.Width# + self.input.Width | |
def get_label(self): | |
return self.label.Text[:-1] | |
def get_value(self): | |
return self.input.Checked | |
class StatePanel(Panel): | |
def __init__(self, label, width, height): | |
super(StatePanel, self).__init__() | |
self.Width = width | |
self.Height = height | |
label_widget = Label() | |
label_widget.Text = label | |
label_widget.Dock = DockStyle.Top | |
label_widget.Height = 20 | |
label_widget.BackColor = Color.Gray | |
label_widget.Font = Font(label_widget.Font, FontStyle.Bold) | |
label_widget.Padding = Padding(3) | |
state_widget = RichTextBox() | |
state_widget.Dock = DockStyle.Top | |
state_widget.Height = height - label_widget.Height | |
# state_widget.Padding = Padding(5) | |
state_widget.Multiline = True | |
state_widget.ScrollBars = RichTextBoxScrollBars.Vertical | |
state_widget.WordWrap = True | |
state_widget.ReadOnly = True | |
self.Controls.Add(state_widget) | |
self.Controls.Add(label_widget) | |
self.label = label_widget | |
self.info = state_widget | |
def log(self, text, error=False): | |
start_selection = self.info.Text.Length | |
self.info.ReadOnly = False | |
self.info.AppendText(str(text)+"\n") | |
self.info.ReadOnly = True | |
if error: | |
# Change text color for error | |
self.info.SelectionStart = start_selection | |
self.info.SelectionLength = self.info.Text.Length - start_selection | |
self.info.SelectionColor = Color.Red | |
# Scroll down the Text box to the bottom | |
self.info.SelectionStart = self.info.Text.Length | |
self.info.ScrollToCaret() | |
def log_error(self, text): | |
self.log(text, True) | |
def clear_log(self): | |
self.info.ReadOnly = False | |
self.info.Text = "" | |
self.info.ReadOnly = True | |
class CaptureRVBWithDither(Form): | |
def __init__(self): | |
self.Text = "Capture RVB with Dither" | |
self.Width = 400 | |
self.Height = 400 | |
# Top | |
self.object_name = ValueInput("Object Name", default_value="Cible") | |
self.object_name.Location = Point(10, 10) | |
self.object_name.input.Width = 100 | |
# Left Attributes | |
self.gain = ValueInput("Gain", default_value=300) | |
self.gain.Location = Point(10, 40) | |
self.gain.input.MaxLength = 5 | |
self.gain.input.Width = 40 | |
self.gain.resize_to_contents() | |
self.exposition = ValueInput("Exposition(s)", default_value=30) | |
self.exposition.Location = Point(10, 70) | |
self.exposition.input.MaxLength = 5 | |
self.exposition.input.Width = 40 | |
self.exposition.resize_to_contents() | |
self.dither = LabeledCheckBox("Dither", default_value=False) | |
self.dither.Location = Point(10, 100) | |
self.dither.resize_to_contents() | |
self.gain.Width = self.exposition.Width | |
self.dither.Width = self.exposition.Width | |
offset = self.exposition.Width + 10 | |
# Right Attributes | |
self.frames = ValueInput("Nbr Frames", default_value=10) | |
self.frames.Location = Point(offset, 40) | |
self.frames.input.MaxLength = 5 | |
self.frames.input.Width = 40 | |
self.frames.resize_to_contents() | |
self.sequences = ValueInput("Nbr Sequences", default_value=3) | |
self.sequences.Location = Point(offset, 70) | |
self.sequences.input.MaxLength = 5 | |
self.sequences.input.Width = 40 | |
self.sequences.resize_to_contents() | |
self.delay = ValueInput("Delay after Dithering", default_value=25) | |
self.delay.Location = Point(offset, 100) | |
self.delay.input.MaxLength = 5 | |
self.delay.input.Width = 40 | |
self.delay.resize_to_contents() | |
self.frames.Width = self.delay.Width | |
self.sequences.Width = self.delay.Width | |
# Folder picker | |
self.target_folder = FolderPicker("Output Folder", default_value=desktop_folder) | |
self.target_folder.Location = Point(10, 140) | |
self.target_folder.input.Width = 180 | |
self.target_folder.resize_to_contents() | |
# Process | |
self.process = StatePanel("Process", width=330, height=130) | |
center_offset = int(self.Width*.5 - self.process.Width*.5) | |
self.process.Location = Point(center_offset, 180) | |
self.process.BorderStyle = BorderStyle.FixedSingle | |
# Button | |
self.start = Button() | |
self.start.Text = 'Start Capturing' | |
self.start.Width = 200 | |
center_offset = int(self.Width*.5 - self.start.Width*.5) | |
bottom_offset = self.Height - self.start.Height - 50 | |
self.start.Location = Point(center_offset, bottom_offset) | |
self.start.Click += self.start_capture | |
self.Controls.Add(self.object_name) | |
self.Controls.Add(self.gain) | |
self.Controls.Add(self.exposition) | |
self.Controls.Add(self.dither) | |
self.Controls.Add(self.frames) | |
self.Controls.Add(self.sequences) | |
self.Controls.Add(self.delay) | |
self.Controls.Add(self.target_folder) | |
self.Controls.Add(self.process) | |
self.Controls.Add(self.start) | |
self.processing = False | |
def start_capture(self, *args): | |
if self.processing: | |
self.end_capture(aborded=True) | |
return | |
self.process.clear_log() | |
# Get and convert values from the Windows form into usable types | |
name = self.object_name.get_value() | |
gain = self.get_int_from(self.gain) | |
if gain is None: return | |
exposition = self.get_float_from(self.exposition) | |
if exposition is None: return | |
dither = self.dither.get_value() | |
frames = self.get_int_from(self.frames) | |
if frames is None: return | |
sequences = self.get_int_from(self.sequences) | |
if sequences is None: return | |
delay = self.get_float_from(self.delay) | |
if delay is None: return | |
output = self.target_folder.get_value() | |
# Call the capture command | |
self.processing = True | |
self.start.Text = "Abord Capturing" | |
capture_RVB_dither( | |
name, | |
gain, | |
exposition, | |
dither, | |
frames, | |
sequences, | |
delay, | |
output, | |
self | |
) | |
def end_capture(self, aborded=False): | |
self.processing = False | |
self.start.Text = "Start Capturing" | |
if aborded: | |
self.process.log_error("Capture Aborded!") | |
def wait_abord(self, second): | |
if not self.processing: | |
return True | |
for _ in range(int(second/wait_precision)): | |
Thread.Sleep(int(wait_precision*1000)) | |
Application.DoEvents() | |
if not self.processing: | |
break | |
if not self.processing: | |
return True | |
return False | |
def wait_call_abord(self, call): | |
if not self.processing: | |
return True | |
while call.poll() is None: | |
Thread.Sleep(100) | |
Application.DoEvents() | |
if not self.processing: | |
break | |
if not self.processing: | |
call.kill() | |
return True | |
return False | |
def get_int_from(self, attribute): | |
try: | |
return attribute.get_value_as_int() | |
except: | |
self.process.log_error( | |
"[Error] Wrong value type for '%s', expected integer: %s"%\ | |
(attribute.get_label(), attribute.get_value()) | |
) | |
return None | |
def get_float_from(self, attribute): | |
try: | |
return attribute.get_value_as_float() | |
except: | |
self.process.log_error( | |
"[Error] Wrong value type for '%s', expected float: %s"%\ | |
(attribute.get_label(), attribute.get_value()) | |
) | |
return None | |
form = CaptureRVBWithDither() | |
Application.Run(form) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment