I did yesterday evening a last test with Numpy.net ... and it work with this.
It is quick ... with the same settings 300x300, noise=50, ...
It can generate 225 image/s, sometimes more (that is much better as 41 images/s).
But ... ach!
2 problems. Here the first is better visible without noise (= 0): The frequency of the images is not constant, around 5 slower period per second.
That is not so good. My goal is the sun observation with a SHG (like a Sol'Ex) and it is absolutely necessary to have a regular capture.
The other problem is the generation of the bitmap and Picturebox.Image ... it take a long-long time: 12 seconds ! Seconds ! not milli or micro !
Something is not good in the iteration of the numpy array values. 12 seconds for getting the values of 300x300 pixels !
Here the script, if someone will test it:
Code: Select all
# *******************************************************************************************
# SharpCap script "xxxxxxxxx.py"
# 2024/08/18 Jean-Francois
#
# Version: 1.0.0: First version
#
# The script works only with a SharpCap PRO version.
# *******************************************************************************************
import os
import time
import datetime
import math
import ctypes
import clr
clr.AddReference("Oxyplot")
clr.AddReference("OxyPlot.WindowsForms ")
clr.AddReference("System.Drawing")
clr.AddReference("System.Windows.Forms")
clr.AddReference("NumpyDotNet.dll")
import OxyPlot
import System.Drawing
import System.Windows.Forms
import NumpyDotNet.np as np
from SharpCap.Base import BufferFrame
from System import Array
from System.Drawing import *
from System.Windows.Forms import *
from System.Threading import Thread, ApartmentState, ParameterizedThreadStart
# .ToBytes() (8 bit) .ToUshorts() (16 bit) and .ToFloats()
# BufferFrame.CopyFrom...()
#dll=ctypes.CDLL(dllfile)
def framehandler(sender, args):
global i, T_meas, W_meas, t0, frameAverage, pos, frameB
if (dumpdata):
try:
dt = (datetime.datetime.now() - t0).total_seconds()
cutout = args.Frame
Stat = cutout.GetStats()
T_meas.append(dt)
W_meas.append(Stat.Item1)
i = i + 1
frameB = cutout.ToUshorts() # 1D array
# for index in range(frameB.Length):
# frameAverage[index] += frameB[index]
frameAverage += frameB
# info = cutout.Info
# bufsize = int(cutout.BufferSize)
# lease = cutout.GetBufferLease()
# frameData_addr = lease.Buffer.ToInt64()
# frameData_ptr = ctypes.cast(frameData_addr, ctypes.POINTER(ctypes.c_ubyte))
# print(frameData_ptr)
# #dll.do_foo(frameData_ptr, info.Width, info.Height, bufsize)
# lease.Dispose()
except:
print("Problem framehandler")
# *****************************************************************************
def WIN_measurement(self):
global dumpdata
global i, T_meas, W_meas, t0, frameAverage
self.WIN_Monitoring.Text = "Monitoring running"
self.WIN_Monitoring.BackColor = Color.Red
self.WIN_Monitoring.Enabled = False
#SharpCap.Transforms.SelectionRect = Rectangle(300, 300,600, 600)
i = 1
T_meas = []
W_meas = []
t0 = 0
image = 0
H = SharpCap.SelectedCamera.Controls.Resolution.CaptureArea.Height
W = SharpCap.SelectedCamera.Controls.Resolution.CaptureArea.Width
frameAverage = np.zeros(W * H, np.Int32)
#frameAverage = Array.CreateInstance(System.Double, W * H)
#frameAverage_byte = Array.CreateInstance(System.Byte, W * H)
frameB = 0
pos = 0
expos_ms = SharpCap.SelectedCamera.Controls.Exposure.ExposureMs
wait_time = 0.1 # waiting time between 2 refresh of Oxyplot graphic
#view.Height = H + 6
#view.Width = W + 6
view.ClientSize = System.Drawing.Size(W + 6, H + 6)
view.pictureBox1.Size = System.Drawing.Size(W, H)
print("Waiting Time: %5.3f" % (wait_time))
print()
print("WIN Transmission:")
print("******************")
dumpdata = True
SharpCap.SelectedCamera.FrameCaptured += framehandler
try:
if (float(self.textBoxTime.Text) > 0.0):
Max_time = float(self.textBoxTime.Text) - wait_time
t0 = datetime.datetime.now()
dt = 0
while (dt < Max_time):
dt = (datetime.datetime.now() - t0).total_seconds()
time.sleep(wait_time)
self.ShowOxyGraphic()
# print("Time:", T_meas)
# print("WIN:", W_meas)
print()
i = i - 1
print("Number: ", i)
mean = sum(W_meas) / len(W_meas)
var = sum(pow(x-mean,2) for x in W_meas) / len(W_meas)
std = math.sqrt(var)
print("Standard deviation 1: " + str("%.6f" % round(std,6)))
else:
print("Measurement time need to be larger than 0 s")
except:
print("Problem 1")
dumpdata = False
SharpCap.SelectedCamera.FrameCaptured -= framehandler
# for index in range(frameAverage_byte.Length):
# frameAverage[index] = frameAverage[index] #/ i
frameAverage = np.divide(frameAverage, i*256)
frameAverage = frameAverage.astype(np.UInt8)
try:
# for index in range(frameAverage_byte.Length):
# frameAverage_byte[index] = int(frameAverage[index] / 256)
flag = Bitmap(W,H)
for i in range(W):
# print(i)
for j in range(H):
index = i + (j * W)
value = frameAverage[index]
#value = 64
flag.SetPixel(i, j, System.Drawing.Color.FromArgb(value, value, value))
view.pictureBox1.Image = flag
except:
print()
print("problem picture")
print()
print("Show Average")
print()
print("Measurement done")
self.WIN_Monitoring.Text = "Start Measurement"
self.WIN_Monitoring.BackColor = Color.Gainsboro
self.WIN_Monitoring.Enabled = True
file_path = os.path.dirname(__file__)
file_name = file_path + "\\" + self.textBoxFileName.Text + ".txt"
file = open(file_name, "w")
for index in range(len(T_meas)):
file.write(str("%.4f" % T_meas[index]) + " " + str("%.4f" % W_meas[index]) + "\n")
file.close()
return()
# *****************************************************************************
class MonitoringWINMenuForm(Form):
def __init__(self):
self.SuspendLayout()
self.InitializeComponent()
self.setupCheckButtons()
self.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi
self.AutoScaleDimensions = SizeF(96, 96)
self.ResumeLayout()
def InitializeComponent(self):
self.Text = "WIN Transmission"
self.ClientSize = System.Drawing.Size(700, 400)
self.TopMost = True
self.labelTime = Label()
self.textBoxTime = TextBox()
self.labelFile = Label()
self.textBoxFileName = TextBox()
self.plot1 = OxyPlot.WindowsForms.PlotView()
self.plot1.Location = System.Drawing.Point(10, 35)
self.plot1.Size = System.Drawing.Size(680, 350)
self.plot1.AutoSize = True
self.Controls.Add(self.labelTime)
self.Controls.Add(self.textBoxTime)
self.Controls.Add(self.labelFile)
self.Controls.Add(self.textBoxFileName)
self.Controls.Add(self.plot1)
self.labelTime.AutoSize = True
self.labelTime.Location = Point(150, 14)
self.labelTime.Name = "labelTime"
self.labelTime.Text = "Measurement time [s]:"
self.textBoxTime.AutoSize = True
self.textBoxTime.Location = Point(280, 13)
self.textBoxTime.Name = "textBoxTime"
self.textBoxTime.Size = Size(35, 20)
self.textBoxTime.Text = "1"
self.labelFile.AutoSize = True
self.labelFile.Location = Point(320, 14)
self.labelFile.Name = "labelFile"
self.labelFile.Text = "File:"
self.textBoxFileName.AutoSize = True
self.textBoxFileName.Location = Point(350, 13)
self.textBoxFileName.Name = "textBoxFileName"
self.textBoxFileName.Size = Size(250, 20)
self.textBoxFileName.Text = "test"
def setupCheckButtons(self):
self.WIN_Monitoring = Button()
self.WIN_Monitoring.Text = "Start Measurement"
self.WIN_Monitoring.Location = Point(20, 10)
self.WIN_Monitoring.Click += self.WIN_monitor
self.WIN_Monitoring.AutoSize = True
self.button_Exit = Button()
self.button_Exit.Text = "Exit"
self.button_Exit.Location = Point(615, 10)
self.button_Exit.Click += self.exit
self.button_Exit.AutoSize = True
self.Controls.Add(self.WIN_Monitoring)
self.Controls.Add(self.button_Exit)
def ShowOxyGraphic(self):
global T_meas, W_meas
self.plotmodel1 = OxyPlot.PlotModel()
self.YAxis1 = OxyPlot.Axes.LinearAxis(Position = OxyPlot.Axes.AxisPosition.Left, Minimum = 0.999*min(W_meas), Maximum = 1.001*max(W_meas))
self.points_start = []
for i in range(0,len(T_meas)):
self.points_start.Add(OxyPlot.DataPoint(T_meas[i],W_meas[i]))
self.serie_1 = OxyPlot.Series.LineSeries()
self.serie_1.Color = OxyPlot.OxyColors.Blue
self.serie_1.MarkerSize = 3
self.serie_1.MarkerType = OxyPlot.MarkerType.Circle
self.serie_1.StrokeThickness = 1
self.serie_1.ItemsSource = self.points_start
self.plotmodel1.Axes.Add(self.YAxis1)
self.plotmodel1.Series.Add(self.serie_1)
self.plot1.Model = self.plotmodel1
def WIN_monitor(self, sender, event):
th = Thread(ParameterizedThreadStart(WIN_measurement))
th.SetApartmentState(ApartmentState.STA)
th.Start(self)
def exit(self, sender, event):
print("Stop Monitoring script")
self.Close()
class MainForm(Form):
def __init__(self):
self.InitializeComponent()
self.pen = System.Drawing.Pen(System.Drawing.Color.Black);
def InitializeComponent(self):
self.pictureBox1 = System.Windows.Forms.PictureBox()
self.SuspendLayout()
H = SharpCap.SelectedCamera.Controls.Resolution.CaptureArea.Height
W = SharpCap.SelectedCamera.Controls.Resolution.CaptureArea.Width
self.pictureBox1.Location = System.Drawing.Point(3, 3)
self.pictureBox1.Name = "pictureBox1"
self.pictureBox1.Size = System.Drawing.Size(W, H)
self.pictureBox1.TabIndex = 0
self.pictureBox1.TabStop = False
self.ClientSize = System.Drawing.Size(W + 6, H + 6)
self.Controls.Add(self.pictureBox1)
self.Name = "MainForm"
self.Text = "Average"
self.ResumeLayout()
form = MonitoringWINMenuForm()
form.StartPosition = FormStartPosition.CenterScreen
form.TopMost = True
form.Show()
view = MainForm()
view.StartPosition = FormStartPosition.CenterScreen
view.TopMost = True
view.Show()Regards,
Jean-Francois