Skip to content

Instantly share code, notes, and snippets.

@delattj
Last active August 8, 2018 15:16
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save delattj/52a8e42bfd023af4b09789d90df99989 to your computer and use it in GitHub Desktop.
Save delattj/52a8e42bfd023af4b09789d90df99989 to your computer and use it in GitHub Desktop.
Capture RGB with Dither (SharpCap 3.0)
# ________________________________________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