stphot/gacquire.py

231 lines
7.7 KiB
Python
Executable File

#!/usr/bin/env python3
# gacquire - gphoto3 interface to stphot.
#
# python-gphoto2 - Python interface to libgphoto2
# http://github.com/jim-easterbrook/python-gphoto2
# Copyright (C) 2015-22 Jim Easterbrook jim@jim-easterbrook.me.uk
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import logging
import locale
import os
import subprocess
import sys
import gphoto2 as gp
import argparse
import os
import sys
import json
import time
import cv2
import zwoasi as asi
import numpy as np
from stphot.io import write_fits_file
def gcapture():
locale.setlocale(locale.LC_ALL, '')
logging.basicConfig(
format='%(levelname)s: %(name)s: %(message)s', level=logging.WARNING)
callback_obj = gp.check_result(gp.use_python_logging())
camera = gp.Camera()
camera.init()
print('Capturing image')
file_path = camera.capture(gp.GP_CAPTURE_IMAGE)
print('Camera file path: {0}/{1}'.format(file_path.folder, file_path.name))
target = os.path.join('/tmp', file_path.name)
print('Copying image to', target)
camera_file = camera.file_get(
file_path.folder, file_path.name, gp.GP_FILE_TYPE_NORMAL)
camera_file.save(target)
camera.exit()
return 0
if __name__ == "__main__":
# Parse arguments
parser = argparse.ArgumentParser(
description="Capture images with a DSLR gphoto2 camera")
parser.add_argument("-s", "--settings", help="JSON file with settings", default="settings.json")
parser.add_argument("-p", "--path", help="Output path", default=None)
# parser.add_argument("-t", "--exptime", help="Exposure time [seconds]", type=float, default=None)
# parser.add_argument("-g", "--gain", help="Gain", type=int, default=None)
# parser.add_argument("-b", "--bin", help="Binning factor", type=int, default=None)
parser.add_argument("-n", "--number", help="Number of images to acquire", type=int, default=None)
# parser.add_argument("-F", "--format", help="Data format [RAW8, RAW16, RGB24]", default=None)
parser.add_argument("-l", "--live", action="store_true", help="Display live image while capturing")
parser.add_argument("-w", "--wait", help="Wait time between exposures [seconds]", type=float, default=0)
parser.add_argument("-d", "--dslr", help="DSLR with gphoto2", type=bool, default=False)
args = parser.parse_args()
# Check arguments
if args.settings == None or args.path == None:
parser.print_help()
sys.exit()
# Read settings
try:
with open(args.settings, "r") as fp:
settings = json.load(fp)
except Exception as e:
print(e)
sys.exit(1)
# Override settings
# if args.exptime is not None:
# settings["exposure"] = f"{int(float(args.exptime) * 1000)}"
# if args.gain is not None:
# settings["gain"] = f"{args.gain}"
# if args.bin is not None:
# settings["bin"] = f"{args.bin}"
# if args.format is not None:
# if args.format == "RAW8":
# settings["type"] = f"{asi.ASI_IMG_RAW8}"
# elif args.format == "RAW16":
# settings["type"] = f"{asi.ASI_IMG_RAW16}"
# elif args.format == "RGB24":
# settings["type"] = f"{asi.ASI_IMG_RGB24}"
# Number of images
if args.number is not None:
nimg = args.number
else:
nimg = 6
# Check path
path = os.path.abspath(args.path)
if not os.path.exists(path):
os.makedirs(path)
# Intialize SDK library
# try:
# asi.init(os.getenv("ZWO_ASI_LIB"))
# except Exception as e:
# print(e)
# sys.exit(1)
# Find cameras
ncam = len(gp.Camera.autodetect())
if ncam == 0:
print("No gphoto2 cameras found")
sys.exit(1)
# Decode settings
# texp_us = 1000 * int(settings["exposure"])
# gain = int(settings["gain"])
# Initialize camera 0
camera = gp.Camera()
camera.init()
#camera_info = camera.get_camera_property()
camera_info = camera.get_summary()
print(camera_info)
# Set control values
# camera.set_control_value(asi.ASI_BANDWIDTHOVERLOAD, int(settings["usb"]))
# camera.set_control_value(asi.ASI_EXPOSURE, texp_us, auto=False)
# camera.set_control_value(asi.ASI_GAIN, gain, auto=False)
# camera.set_control_value(asi.ASI_WB_B, int(settings["wbb"]))
# camera.set_control_value(asi.ASI_WB_R, int(settings["wbr"]))
# camera.set_control_value(asi.ASI_GAMMA, int(settings["gamma"]))
# camera.set_control_value(asi.ASI_BRIGHTNESS, int(settings["brightness"]))
# camera.set_control_value(asi.ASI_FLIP, int(settings["flip"]))
# camera.set_control_value(asi.ASI_AUTO_MAX_BRIGHTNESS, 80)
# camera.disable_dark_subtract()
# camera.set_roi(bins=int(settings["bin"]))
# Force any single exposure to be halted
#try:
# camera.stop_video_capture()
# camera.stop_exposure()
#except (KeyboardInterrupt, SystemExit):
# raise
#except:
# pass
# Set image format
# if int(settings["type"]) == asi.ASI_IMG_RAW8:
# camera.set_image_type(asi.ASI_IMG_RAW8)
# elif int(settings["type"]) == asi.ASI_IMG_RGB24:
# camera.set_image_type(asi.ASI_IMG_RGB24)
# elif int(settings["type"]) == asi.ASI_IMG_RAW16:
# camera.set_image_type(asi.ASI_IMG_RAW16)
# else:
# camera.set_image_type(asi.ASI_IMG_RAW8)
# Forever loop
for i in range(nimg):
print(f"Capturing image {i} of {nimg}")
# Capture frame
t0 = time.time()
# XXX
img = camera.capture(gp.GP_CAPTURE_IMAGE)
exit()
# Display Frame
if args.live is True:
cv2.imshow("Capture", img)
cv2.waitKey(1)
# Get settings
camera_settings = camera.get_control_values()
# Extract settings
# texp_us = camera_settings["Exposure"]
# texp = float(texp_us) / 1000000
# gain = camera_settings["Gain"]
# temp = float(camera_settings["Temperature"]) / 10
# Format start time
nfd = "%s.%03d" % (time.strftime("%Y-%m-%dT%T",
time.gmtime(t0)), int((t0 - np.floor(t0)) * 1000))
# print(nfd, texp, gain, temp)
# Store FITS file
# write_fits_file(os.path.join(path, "%s.fits" % nfd), np.flipud(img), nfd, texp, gain, temp)
write_fits_file(os.path.join(path, "%s.fits" % nfd), np.flipud(img), nfd)
#print(settings["type"], asi.ASI_IMG_RAW8, asi.ASI_IMG_RGB24, asi.ASI_IMG_RAW16)
# Get RGB image
if int(settings["type"]) == asi.ASI_IMG_RAW8:
ny, nx = img.shape
rgb_img = cv2.cvtColor(img, cv2.COLOR_BAYER_BG2BGR)
elif int(settings["type"]) == asi.ASI_IMG_RGB24:
ny, nx, nc = img.shape
rgb_img = img
elif int(settings["type"]) == asi.ASI_IMG_RAW16:
ny, nx = img.shape
img_8bit = np.clip((img/256).astype("uint8"), 0, 255)
rgb_img = cv2.cvtColor(img_8bit, cv2.COLOR_BAYER_BG2BGR)
# Store image
cv2.imwrite(os.path.join(path, "%s.jpg" % nfd), rgb_img)
# Wait
if args.wait > 0:
time.sleep(args.wait)
# Stop capture
camera.stop_video_capture()
# Release device
if args.live is True:
cv2.destroyAllWindows()