View with center and corners

Got an idea for something that SharpCap should do? Share it here.
Forum rules
'+1' posts are welcome in this area of the forums to indicate your support for a particular feature suggestion. Suggestions that get the most +1's will be seriously considered for inclusion in future versions of SharpCap.
Astrojan
Posts: 3
Joined: Sun Sep 08, 2019 7:37 pm

View with center and corners

#1

Post by Astrojan »

Hi Robin,

is it possible that you create a view with the center and the four corners of the camera chip at same time if you use a zoom level ? In the moment you only see the choosen area and if I want to see the star quality in the corners I have to move the area from corner to corner. With this view you have a good overview at same time.
CenterAndCorners.png
CenterAndCorners.png (333.27 KiB) Viewed 2754 times
Best regards
Jan
User avatar
carlomuccini
Posts: 253
Joined: Mon Apr 27, 2020 12:42 pm
Location: Montecatini Terme (PT), Italy
Contact:

Re: View with center and corners

#2

Post by carlomuccini »

Use Astap to load the image saved and press F6

Carlo
Astrojan
Posts: 3
Joined: Sun Sep 08, 2019 7:37 pm

Re: View with center and corners

#3

Post by Astrojan »

Hi, thank you. But I want it in Live View.

Best regards
Jan
User avatar
admin
Site Admin
Posts: 17342
Joined: Sat Feb 11, 2017 3:52 pm
Location: Vale of the White Horse, UK
Contact:

Re: View with center and corners

#4

Post by admin »

Hi,

I think this suggestion has appeared before, but I never got around to it. Actually, it might work well as one of the 'Display FX' dropdown options, which would possibly make it quite simple to achieve. I will have think about it.

cheers,

Robin
Astrojan
Posts: 3
Joined: Sun Sep 08, 2019 7:37 pm

Re: View with center and corners

#5

Post by Astrojan »

thank you

Jan
Jean-Francois
Posts: 822
Joined: Sun Oct 13, 2019 10:52 am
Location: Germany

Re: View with center and corners

#6

Post by Jean-Francois »

Hello,

Or you try this small script ...

It is not finish. It has a big problem with the 16 bit MONO images (it simply not work ... yet).
So please, first set your camera to MONO8 (if you have a monochrome camera).

Robin, why the MONO16 and RAW16 are not working ?

Save the following code in a *py file.

Code: Select all

# *******************************************************************************************
# SharpCap script "xxxxxxxxx.py"
# 2024/08/26 Jean-Francois
#
# Version: 1.0.0:   First version
#
# The script works only with a SharpCap PRO version.
# *******************************************************************************************

import os
import math
import clr
clr.AddReference("System.Drawing")
clr.AddReference("System.Windows.Forms")

import System.Drawing
import System.Windows.Forms

from System import Array
from System.Drawing import *
from System.Windows.Forms import *
from System.Threading import Thread, ApartmentState, ParameterizedThreadStart

H = SharpCap.SelectedCamera.Controls.Resolution.CaptureArea.Height
W = SharpCap.SelectedCamera.Controls.Resolution.CaptureArea.Width

Boxsize = 100

bH = Boxsize
bW = Boxsize

Rect_1 = Rectangle(0, 0, bW, bH)
Rect_2 = Rectangle((W-bW)//2, 0, bW, bH)
Rect_3 = Rectangle(W - bW, 0, bW, bH)
Rect_4 = Rectangle(0, (H-bH)//2, bW, bH)
Rect_5 = Rectangle((W-bW)//2, (H-bH)//2, bW, bH)
Rect_6 = Rectangle(W - bW, (H-bH)//2, bW, bH)
Rect_7 = Rectangle(0, H - bH, bW, bH)
Rect_8 = Rectangle((W-bW)//2, H - bH, bW, bH)
Rect_9 = Rectangle(W - bW, H - bH, bW, bH)

# RGB32     Format32bppRgb
# RGB24     Format24bppRgb
# RGB48     Format48bppRgb
# MONO8     Format8bppIndexed
# MONO16    Format16bppGrayScale
# RAW8      Format32bppRgb
# RAW16     Format64bppArgb

frame = 0

def framehandler(sender, args):
    global frame
    if (dumpdata):
        try:
            frame = args.Frame.GetFrameBitmap()

            bitmap = Bitmap(3 * bW + 2, 3 * bH + 2)#, frame.PixelFormat)

            gr = Graphics.FromImage(bitmap)

            gr.DrawImage(frame, Rectangle(       0,        0, bW, bH), Rect_1, GraphicsUnit.Pixel)
            gr.DrawImage(frame, Rectangle(  bW + 1,        0, bW, bH), Rect_2, GraphicsUnit.Pixel)
            gr.DrawImage(frame, Rectangle(2*bW + 2,        0, bW, bH), Rect_3, GraphicsUnit.Pixel)
            gr.DrawImage(frame, Rectangle(       0,   bH + 1, bW, bH), Rect_4, GraphicsUnit.Pixel)
            gr.DrawImage(frame, Rectangle(  bW + 1,   bH + 1, bW, bH), Rect_5, GraphicsUnit.Pixel)
            gr.DrawImage(frame, Rectangle(2*bW + 2,   bH + 1, bW, bH), Rect_6, GraphicsUnit.Pixel)
            gr.DrawImage(frame, Rectangle(       0, 2*bH + 2, bW, bH), Rect_7, GraphicsUnit.Pixel)
            gr.DrawImage(frame, Rectangle(  bW + 1, 2*bH + 2, bW, bH), Rect_8, GraphicsUnit.Pixel)
            gr.DrawImage(frame, Rectangle(2*bW + 2, 2*bH + 2, bW, bH), Rect_9, GraphicsUnit.Pixel)

            form.pictureBox1.Image = bitmap

        except:
            print("Problem framehandler")


# *****************************************************************************
def Nine_zone(self):
    global dumpdata
    global bH, bW, Rect_1, Rect_2, Rect_3, Rect_4, Rect_5, Rect_6, Rect_7, Rect_8, Rect_9

    Boxsize = int(self.textBoxSize.Text)
    bH = Boxsize
    bW = Boxsize

    Rect_1 = Rectangle(0, 0, bW, bH)
    Rect_2 = Rectangle((W-bW)//2, 0, bW, bH)
    Rect_3 = Rectangle(W - bW, 0, bW, bH)
    Rect_4 = Rectangle(0, (H-bH)//2, bW, bH)
    Rect_5 = Rectangle((W-bW)//2, (H-bH)//2, bW, bH)
    Rect_6 = Rectangle(W - bW, (H-bH)//2, bW, bH)
    Rect_7 = Rectangle(0, H - bH, bW, bH)
    Rect_8 = Rectangle((W-bW)//2, H - bH, bW, bH)
    Rect_9 = Rectangle(W - bW, H - bH, bW, bH)

    self.pictureBox1.Size = System.Drawing.Size(3*Boxsize + 2, 3*Boxsize + 2)

    if (3*Boxsize + 2 > 450):
        new_width = int((3*Boxsize + 2)/1.476)
        self.ClientSize = System.Drawing.Size(new_width, new_width + 40)
        self.AutoScaleDimensions = SizeF(96, 96)
    if (3*Boxsize + 2 < 450):
        new_width = 300
        self.ClientSize = System.Drawing.Size(new_width, new_width + 40)
        self.AutoScaleDimensions = SizeF(96, 96)

    if (self.Nine_zone.Text == "Start"):
        self.Nine_zone.Text = "Stop"
        self.Nine_zone.BackColor = Color.Red
        dumpdata = True
        SharpCap.SelectedCamera.FrameCaptured += framehandler

    elif (self.Nine_zone.Text == "Stop"):
        self.Nine_zone.Text = "Start"
        self.Nine_zone.BackColor = Color.Gainsboro
        dumpdata = False
        SharpCap.SelectedCamera.FrameCaptured -= framehandler

    print()
    print("Nine Zones:")
    print("*****************")

    return()

# *****************************************************************************

class Nine_zoneWINMenuForm(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 = "Nine Zones"
        self.ClientSize = System.Drawing.Size(300, 340)
        self.TopMost = True

    def setupCheckButtons(self):
        self.Nine_zone = Button()
        self.Nine_zone.Text = "Start"
        self.Nine_zone.Location = Point(20, 10)
        self.Nine_zone.Click += self.Nine_zone_meas
        self.Nine_zone.AutoSize = True

        self.labelSize = Label()
        self.labelSize.AutoSize = True
        self.labelSize.Location = Point(110, 14)
        self.labelSize.Name = "labelSize"
        self.labelSize.Text = "Size:"

        self.textBoxSize = TextBox()
        self.textBoxSize.AutoSize = True
        self.textBoxSize.Location = Point(145, 12)
        self.textBoxSize.Name = "textBoxSize"
        self.textBoxSize.Size = Size(35, 20)
        self.textBoxSize.Text = str(Boxsize)

        self.button_Exit = Button()
        self.button_Exit.Text = "Exit"
        self.button_Exit.Location = Point(200, 10)
        self.button_Exit.Click += self.exit
        self.button_Exit.AutoSize = True

        self.pictureBox1 = System.Windows.Forms.PictureBox()
        self.pictureBox1.Location = System.Drawing.Point(3, 40)
        self.pictureBox1.Name = "pictureBox1"
        self.pictureBox1.Size = System.Drawing.Size(3*Boxsize + 2, 3*Boxsize + 2)
        self.pictureBox1.TabIndex = 0
        self.pictureBox1.TabStop = False

        self.Controls.Add(self.Nine_zone)
        self.Controls.Add(self.labelSize)
        self.Controls.Add(self.textBoxSize)
        self.Controls.Add(self.button_Exit)
        self.Controls.Add(self.pictureBox1)

    def Nine_zone_meas(self, sender, event):
        th = Thread(ParameterizedThreadStart(Nine_zone))
        th.SetApartmentState(ApartmentState.STA)
        th.Start(self)

    def exit(self, sender, event):
        print("Stop script")
        dumpdata = False
        SharpCap.SelectedCamera.FrameCaptured -= framehandler
        self.Close()


form = Nine_zoneWINMenuForm()
form.StartPosition = FormStartPosition.CenterScreen
form.TopMost = True
form.Show()
Nine_zones_Test_1.jpg
Nine_zones_Test_1.jpg (805.47 KiB) Viewed 2680 times
You can change the size of the sub-zone. The script will show 9 sectors (4 corners + top, bottom, left, right and centre).
The scaling of the window may not work properly with a different monitor pixel scaling (windows 100%, 125% or 150%).

The 9 sectors are the image before the stretching.

Robin, is it possible to have the image after the "Display Histogram Stretch" ?

Regards,
Jean-Francois
Borodog
Posts: 479
Joined: Fri Jan 01, 2021 7:25 pm

Re: View with center and corners

#7

Post by Borodog »

Just wanted to +1 this request, as it would be an extremely useful thing while dialing in backspacing and tilt adjustment.

PS this view is usually called "aberration inspector".
User avatar
admin
Site Admin
Posts: 17342
Joined: Sat Feb 11, 2017 3:52 pm
Location: Vale of the White Horse, UK
Contact:

Re: View with center and corners

#8

Post by admin »

Hi,

Jean-Francois beats me to it again :)

On the problems with 16 bit images, the support for working with these in Windows native bitmaps is pretty patchy, so best avoided if possible. The best bet would be to make a lower bit depth copy if the incoming frame if it is 16 bit (use frame.ChangeBitDepth(8), but don't forget to .Release() the result).

You cannot intercept the in 'stretched' form, but you can apply a stretch yourself - create a 'ReciprocalLevelStretch' object (in SharpCap.Base.Interfaces) and call frame.DisplayTransform(stretch) - that should give you a stretched 8 bit frame that you can work with.

Also, you should really try to avoid talking to the UI from the frame handler directly - that's a cross-thread error really, although sometimes you get away with it. There should be a way using form.BeginInvoke() and passing a lambda that actually attaches the bitmap to the picturebox - that lambda will be run in the UI thread for the form, making all the Windows Forms code happy.

cheers,

Robin
Jean-Francois
Posts: 822
Joined: Sun Oct 13, 2019 10:52 am
Location: Germany

Re: View with center and corners

#9

Post by Jean-Francois »

Hello Robin,

OK for the 16 bit bitmap in Windows. I saw this problem in some forum.

Concerning the .Release() ... I have fast no idea where and when to use it. Alternative is .Dispose(). What is the difference ?

For the stretch of the image ... It seems each time so easy when you explain something ... but at the end I need several days to use it after 100 of try (and fast so much crash).

For the talking to the UI from the frame handler ... that is the next example ... what ?
OK, I will first need to read >50 webpage explaining what you write in one sentence :-)

Jean-Francois
User avatar
admin
Site Admin
Posts: 17342
Joined: Sat Feb 11, 2017 3:52 pm
Location: Vale of the White Horse, UK
Contact:

Re: View with center and corners

#10

Post by admin »

Hi,

Dispose() is part of the 'Disposable' pattern, widely used in .NET to clean up resources when they are done with. It's great as long as only one bit of code needs to keep track of use of the resource. However, there are places in SharpCap where two parts of the code might be working at the same time with a frame - Dispose() is no good in that circumstance as neither can call Dispose() because the other might not be finished. Instead, frames are reference counted and you use 'AddRef' and 'Release' to adjust the reference count. When the reference count drops to zero, nothing is using the frame any more and it cleans itself up.

In the case here though, it's a bit simpler - lots of things that can transform a frame (like changing bit depth) will return a new frame with a reference count of 1, so you just need to call .Release() when you are done with that copy to make sure it gets cleaned up.

The BeginInvoke thing is fairly simple once you know the trick... In python it would look something like this

Code: Select all

from System.Windows.Forms import Form
form = Form()
form.Show()
def function():
	print ("hello")
	
// later, in another thread
form.BeginInvoke(lambda: function())

Passing the lambda to BeginInvoke causes code of the lambda to be run in the thread which the form lives on, rather than the thread that is calling BeginInvoke. The lambda will run asynchronously (you can use .Invoke() if you *need* synchronous behaviour, but that can cause deadlocks if not handled carefully).

Any code that updates the UI (sets text, updates properties on forms, controls, things on forms, etc) should be run in the thread that the form lives on, not in one of SharpCap's threads that send events. Sometimes you can get away with breaking this rule, but it won't be reliable...

cheers,

Robin
Post Reply