Showing posts with label Camera Module. Show all posts
Showing posts with label Camera Module. Show all posts

Monday, March 22, 2021

min. version of RPi/Python Code to control Camera Module with preview on local HDMI

It's a minimum version of my another exercise "RPi/Python Code to control Camera Module with preview on local HDMI"; with minimum functions preview and capture only, using PyQt5 GUI, fixed resolution 240x240, and display the captured image on GUI. You can also choice save file name; image.jpg or img_<timestamp>.jpg, under Desktop folder. It's used to prepare images for my coming exercise "Raspberry Pi/Python send image to ESP32/MicroPython via WiFi TCP socket".

In my usage scenario: The Raspberry Pi 4B/8G is installed with HQ Camera Module (mount with manual focus lens) and a 4 inch HDMI IPS Touch Display. Remote control with Android with xrdp/Microsoft Remote Desktop. Such that I can control camera on remote Android device, adjust focus/aperture on the lens, and check the effect on local HDMI preview at real-time.


Python3 code, qCam240_20210323.py
import sys
import picamera
from pkg_resources import require
import time
import picamera

from PyQt5.QtWidgets import (QApplication, QWidget,
                             QPushButton, QLabel, QRadioButton,
                             QMessageBox, QHBoxLayout, QVBoxLayout)
from PyQt5.QtGui import QPixmap, QImage
from PyQt5.Qt import qRed, qGreen, qBlue
from signal import signal, SIGINT

print(sys.version)
print(require('picamera'))

rpi_icon = 'rpi_icon_240.png'

class AppWindow(QWidget):
    
    camPreviewState = False  #not in Preview
    
    def __init__(self):
        super().__init__()

        self.camera = picamera.PiCamera()
        self.camera.resolution = (240, 240)
        
        lbSysInfo = QLabel('Python:\n' + sys.version)
        lbPicameraInfo = QLabel(str(require('picamera')))
        vboxInfo = QVBoxLayout()
        vboxInfo.addWidget(lbSysInfo)
        vboxInfo.addWidget(lbPicameraInfo)
        
        #setup UI
        btnPreview = QPushButton("Start Preview", self)
        btnPreview.clicked.connect(self.evBtnPreviewClicked)
        btnCapture = QPushButton("Capture", self)
        btnCapture.clicked.connect(self.evBtnCaptureClicked)
        
        lbFileName = QLabel('save as (Desktop/):')
        self.rbtnImage = QRadioButton('image.jpg')
        self.rbtnImage.setChecked(True)
        self.rbtnStamp = QRadioButton('img_<timestamp>.jpg')
        
        vboxCamControl = QVBoxLayout()
        vboxCamControl.addWidget(btnPreview)
        vboxCamControl.addWidget(btnCapture)
        vboxCamControl.addWidget(lbFileName)
        vboxCamControl.addWidget(self.rbtnImage)
        vboxCamControl.addWidget(self.rbtnStamp)
        vboxCamControl.addStretch()
        
        self.lbImg = QLabel(self)
        self.lbImg.resize(240, 240)
        self.lbImg.setStyleSheet("border: 1px solid black;")
        
        try:
            with open(rpi_icon):
                pixmap = QPixmap(rpi_icon)
                self.lbImg.setPixmap(pixmap)
        except FileNotFoundError:
            print('File Not Found Error')
        
        hboxCam = QHBoxLayout()
        hboxCam.addWidget(self.lbImg)
        hboxCam.addLayout(vboxCamControl)

        self.lbPath = QLabel(self)

        vboxMain = QVBoxLayout()
        vboxMain.addLayout(vboxInfo)
        vboxMain.addLayout(hboxCam)
        vboxMain.addWidget(self.lbPath)
        vboxMain.addStretch()
        self.setLayout(vboxMain)
        
        self.setGeometry(100, 100, 500,400)
        self.show()

    def evBtnPreviewClicked(self):
        if self.camPreviewState:
            print('Stop Preview')
            self.camera.stop_preview()
            self.sender().setText('Start Preview')
            self.camPreviewState = False
        else:
            print('Start Preview')
            self.camera.start_preview()
            self.sender().setText('Stop Preview')
            self.camPreviewState = True
        
    def evBtnCaptureClicked(self):
        print('evBtnCaptureClicked()')
        print("Capture")
        
        if self.rbtnImage.isChecked():
            targetPath="/home/pi/Desktop/image.jpg" 
        else:
            timeStamp = time.strftime("%Y%m%d-%H%M%S")
            targetPath="/home/pi/Desktop/img_"+timeStamp+".jpg"
        
        print(targetPath)
        
        self.camera.capture(targetPath)
        self.lbPath.setText(targetPath)
        
        try:
            with open(targetPath):
                pixmap = QPixmap(targetPath)
                self.lbImg.setPixmap(pixmap)
                
                #as a exercise, get some info from pixmap
                print('\npixmap:')
                print(pixmap)
                print(type(pixmap))
                print(str(pixmap.width()) + " : " + str(pixmap.height()))
                print()
                
                print('convert to Image')
                qim = pixmap.toImage()
                print(qim)
                print(type(qim))
                print()
                
                print('read a pixel from image')
                qrgb = qim.pixel(0, 0)
                print(hex(qrgb))
                print(type(qrgb))
                
                r, g, b = qRed(qrgb), qGreen(qrgb), qBlue(qrgb) 
                print([hex(r), hex(g), hex(b)])
                print()

        except FileNotFoundError:
            print('File Not Found Error')
        
    def closeEvent(self, event):
        confirmClose = QMessageBox.question(self,
                                            "Quit App?",
                                            "Confirm to Quit?",
                                            QMessageBox.No | QMessageBox.Yes,
                                            QMessageBox.Yes)
        if confirmClose == QMessageBox.Yes:
            print('Confirmed Close')
            self.camera.close()
            event.accept()
        else:
            event.ignore()
        
if __name__ == '__main__':
    print('run __main__')
    app = QApplication(sys.argv)
    window = AppWindow()
    sys.exit(app.exec_())

print("- bye -")

Download the thumbnail image, save as "rpi_icon_240.png" in the same folder. Used as a default image only.



Tuesday, March 9, 2021

RPi/Python Code to control Camera Module with preview on local HDMI

It's a Python3 code run on Raspberry Pi to control Camera Module with various setting. The preview display on local HDMI. 


In my usage scenario: The Raspberry Pi 4B/8G is installed with HQ Camera Module (mount with manual focus lens) and a 4 inch HDMI IPS Touch Display. Remote control with Android with xrdp/Microsoft Remote Desktop. Such that I can control and change setting on remote Android device, adjust focus/aperture on the lens, and check the effect on local HDMI preview at real-time.

It's a long time ago, I make a similar code with preview stream video, both control and preview on remote desktop, Python to capture image from Pi Camera Module, with image effects. But I'm not satisfied by the delay of stream video, that's why I re-develop this code again.


The lens shown on the video is a Nikkor ais 28mm f2.8 manual focus lens, connected to HQ Camera Module via a Nikon F to C mount adapter.

rpiCam_20210309a.py
import sys
import picamera
from pkg_resources import require
import time

"""
ref: Picamera
https://picamera.readthedocs.io/en/release-1.13/
"""

#from tkinter import *
#tkinter for Python 3
import tkinter as tk
from tkinter import ttk

def close_window():
    #close tasks
    camera.close()
    print("Camera closed")
    
    print("close_window()")
    print("Window closed")
    root.destroy()

#event callback functions
def evStartPreviewBtnPressed():
    print("Start Preview")
    camera.start_preview()

def evStopPreviewBtnPressed():
    print("Stop Preview")
    camera.stop_preview()

def evCaptureBtnPressed():
    print("Capture")
    timeStamp = time.strftime("%Y%m%d-%H%M%S")
    targetPath="/home/pi/Desktop/img_"+timeStamp+".jpg"
    print(targetPath)
    camera.capture(targetPath)
    
def cmdScaleSharpness(new_value):
    camera.sharpness = scaleSharpness.get()
    print("sharpness: " + str(camera.sharpness))
    
def cmdScaleContrast(new_value):
    camera.contrast = scaleContrast.get()
    print("contrast: " + str(camera.contrast))
    
def cmdScaleBrightness(new_value):
    camera.brightness = scaleBrightness.get()
    print("brightness: " + str(camera.brightness))
    
def cmdScaleSaturation(new_value):
    camera.saturation = scaleSaturation.get()
    print("saturation: " + str(camera.saturation))
    
def cmdScaleExpCompensation(NEW_VALUE):
    camera.exposure_compensation = scaleExpCompensation.get()
    print("exposure_compensation: " + str(camera.exposure_compensation))
    
def cmdRB_Iso():
    camera.iso = varIso.get()
    print("iso: " + str(camera.iso))

print(sys.version)
print(require('picamera'))
strInfo = str(sys.version) + str(require('picamera'))
type(sys.version)
type(require('picamera'))

#Prepare camera
camera = picamera.PiCamera()
#set default
camera.sharpness = +5
camera.contrast = 0
camera.brightness = 50
camera.saturation = 0
camera.iso = 100
camera.video_stabilization = False
camera.exposure_compensation = 0
camera.exposure_mode = 'auto'
camera.meter_mode = 'average'
camera.awb_mode = 'auto'
camera.image_effect = 'none'
camera.color_effects = None
camera.rotation = 0
camera.hflip = False
camera.vflip = False
camera.crop = (0.0, 0.0, 1.0, 1.0)
  
# not work for HQ
#camera.resolution = (4056, 3040)  # HQ
#camera.resolution = (2592, 1944)  # V1
camera.resolution = (3280, 2464)  # V2
#end of set default

SCALE_WIDTH = 940;

#Prepare GUI
root = tk.Tk()
#root.geometry("650x550")
root.geometry("960x800")
root.wm_title("doCamII")
root.protocol("WM_DELETE_WINDOW", close_window)

labelInfo = tk.Label(root,
                  text=strInfo, fg="gray",
                  font=("Helvetica", 14))
labelInfo.pack()

#Main control
frameMain = tk.Frame(root, bg="lightgray")

btnStartPreview = tk.Button(frameMain, text="Start Preview",
                    command=evStartPreviewBtnPressed)
btnStopPreview = tk.Button(frameMain, text="Stop Preview",
                    command=evStopPreviewBtnPressed)
btnStartPreview.grid(row=2, column=0, sticky=tk.W+tk.E)
btnStopPreview.grid(row=2, column=1, sticky=tk.W+tk.E)

btnCapture = tk.Button(frameMain, text="Capture",
                    command=evCaptureBtnPressed)
btnCapture.grid(row=3, columnspan=2, sticky=tk.W+tk.E)
frameMain.pack(padx=10,pady=10)

#Setting
notebook = ttk.Notebook(root)
frame1 = ttk.Frame(notebook)
frame2 = ttk.Frame(notebook)
frame3 = ttk.Frame(notebook)
notebook.add(frame1, text='Setting 1')
notebook.add(frame2, text='Setting 2')
notebook.add(frame3, text='Setting 3')
notebook.pack()

lfSharpness = ttk.LabelFrame(frame1, text="sharpness")
lfSharpness.pack(fill="x", expand="no", anchor=tk.N)
scaleSharpness = tk.Scale(
    lfSharpness,
    from_=-100, to=100,
    length=SCALE_WIDTH,
    orient=tk.HORIZONTAL,
    command=cmdScaleSharpness)
scaleSharpness.set(camera.sharpness)
scaleSharpness.pack()

lfContrast = ttk.LabelFrame(frame1, text="contrast")
lfContrast.pack(fill="x", expand="no", anchor=tk.N)
scaleContrast = tk.Scale(
    lfContrast,
    from_=-100, to=100,
    length=SCALE_WIDTH,
    orient=tk.HORIZONTAL,
    command=cmdScaleContrast)
scaleContrast.set(camera.contrast)
scaleContrast.pack()

lfBrightness = ttk.LabelFrame(frame1, text="brightness")
lfBrightness.pack(fill="x", expand="no", anchor=tk.N)
scaleBrightness = tk.Scale(
    lfBrightness,
    from_=0, to=100,
    length=SCALE_WIDTH,
    orient=tk.HORIZONTAL,
    command=cmdScaleBrightness)
scaleBrightness.set(camera.brightness)
scaleBrightness.pack()

lfSaturation = ttk.LabelFrame(frame1, text="saturation")
lfSaturation.pack(fill="x", expand="no", anchor=tk.N)
scaleSaturation = tk.Scale(
    lfSaturation,
    from_=-100, to=100,
    length=SCALE_WIDTH,
    orient=tk.HORIZONTAL,
    command=cmdScaleSaturation)
scaleSaturation.set(camera.saturation)
scaleSaturation.pack()

lfExpCompensation = ttk.LabelFrame(frame1, text="exposure_compensation")
lfExpCompensation.pack(fill="x", expand="no", anchor=tk.N)
scaleExpCompensation = tk.Scale(
    lfExpCompensation,
    from_=-25, to=25,
    length=SCALE_WIDTH,
    orient=tk.HORIZONTAL,
    command=cmdScaleExpCompensation)
scaleExpCompensation.set(camera.exposure_compensation)
scaleExpCompensation.pack()

#==========================================================
varIso = tk.IntVar()
varIso.set(camera.iso)
lfIso = ttk.LabelFrame(frame2, text="iso")
lfIso.pack(fill="x", expand="no", anchor=tk.N)
tk.Radiobutton(lfIso, variable=varIso,
        text='0 (auto)',value=0,command=cmdRB_Iso).pack(
            anchor=tk.W, side=tk.LEFT)
tk.Radiobutton(lfIso, variable=varIso,
        text='100',value=100,command=cmdRB_Iso).pack(
            anchor=tk.W, side=tk.LEFT)
tk.Radiobutton(lfIso, variable=varIso,
        text='200',value=200,command=cmdRB_Iso).pack(
            anchor=tk.W, side=tk.LEFT)
tk.Radiobutton(lfIso, variable=varIso,
        text='400',value=400,command=cmdRB_Iso).pack(
            anchor=tk.W, side=tk.LEFT)
tk.Radiobutton(lfIso, variable=varIso,
        text='800',value=800,command=cmdRB_Iso).pack(
            anchor=tk.W, side=tk.LEFT)
tk.Radiobutton(lfIso, variable=varIso,
        text='1600',value=1600,command=cmdRB_Iso).pack(
            anchor=tk.W, side=tk.LEFT)
#==========================================================
#-- meter_mode command
def cmdMeterMode():
    camera.meter_mode = varMeterMode.get()
    print("meter_mode: " + str(camera.meter_mode))
#-- exposure_mode
lfMeterMode = ttk.LabelFrame(frame2, text="meter_mode")
lfMeterMode.pack(fill="x", expand="no", anchor=tk.N)
varMeterMode = tk.StringVar()
varMeterMode.set(camera.meter_mode)

tk.Radiobutton(lfMeterMode, variable=varMeterMode,
        text='average',value='average',command=cmdMeterMode).pack(
            anchor=tk.W, side=tk.LEFT)
tk.Radiobutton(lfMeterMode, variable=varMeterMode,
        text='spot',value='spot',command=cmdMeterMode).pack(
            anchor=tk.W, side=tk.LEFT)
tk.Radiobutton(lfMeterMode, variable=varMeterMode,
        text='backlit',value='backlit',command=cmdMeterMode).pack(
            anchor=tk.W, side=tk.LEFT)
tk.Radiobutton(lfMeterMode, variable=varMeterMode,
        text='matrix',value='matrix',command=cmdMeterMode).pack(
            anchor=tk.W, side=tk.LEFT)


#==========================================================
#-- exposure_mode command
def cmdEposureMode():
    camera.exposure_mode = varExposureMode.get()
    print("exposure_mode: " + str(camera.exposure_mode))
#-- exposure_mode
lfExpMode = ttk.LabelFrame(frame2, text="exposure_mode")
lfExpMode.pack(fill="x", expand="no", anchor=tk.N)
varExposureMode = tk.StringVar()
varExposureMode.set(camera.exposure_mode)
lfExposure_mode1 = ttk.Frame(lfExpMode)
lfExposure_mode1.pack(fill="x", expand="no", anchor=tk.N)
lfExposure_mode2 = ttk.Frame(lfExpMode)
lfExposure_mode2.pack(fill="x", expand="no", anchor=tk.N)

tk.Radiobutton(lfExposure_mode1, variable=varExposureMode,
        text='off',value='off',command=cmdEposureMode).pack(
            anchor=tk.W, side=tk.LEFT)
tk.Radiobutton(lfExposure_mode1, variable=varExposureMode,
        text='auto',value='auto',command=cmdEposureMode).pack(
            anchor=tk.W, side=tk.LEFT)
tk.Radiobutton(lfExposure_mode1, variable=varExposureMode,
        text='night',value='night',command=cmdEposureMode).pack(
            anchor=tk.W, side=tk.LEFT)

tk.Radiobutton(lfExposure_mode1, variable=varExposureMode,
        text='nightpreview',value='nightpreview',command=cmdEposureMode).pack(
            anchor=tk.W, side=tk.LEFT)
tk.Radiobutton(lfExposure_mode1, variable=varExposureMode,
        text='backlight',value='backlight',command=cmdEposureMode).pack(
            anchor=tk.W, side=tk.LEFT)
tk.Radiobutton(lfExposure_mode1, variable=varExposureMode,
        text='spotlight',value='spotlight',command=cmdEposureMode).pack(
            anchor=tk.W, side=tk.LEFT)
tk.Radiobutton(lfExposure_mode1, variable=varExposureMode,
        text='sports',value='sports',command=cmdEposureMode).pack(
            anchor=tk.W, side=tk.LEFT)
tk.Radiobutton(lfExposure_mode1, variable=varExposureMode,
        text='snow',value='snow',command=cmdEposureMode).pack(
            anchor=tk.W, side=tk.LEFT)

tk.Radiobutton(lfExposure_mode2, variable=varExposureMode,
        text='beach',value='beach',command=cmdEposureMode).pack(
            anchor=tk.W, side=tk.LEFT)
tk.Radiobutton(lfExposure_mode2, variable=varExposureMode,
        text='verylong',value='verylong',command=cmdEposureMode).pack(
            anchor=tk.W, side=tk.LEFT)
tk.Radiobutton(lfExposure_mode2, variable=varExposureMode,
        text='fixedfps',value='fixedfps',command=cmdEposureMode).pack(
            anchor=tk.W, side=tk.LEFT)
tk.Radiobutton(lfExposure_mode2, variable=varExposureMode,
        text='antishake',value='antishake',command=cmdEposureMode).pack(
            anchor=tk.W, side=tk.LEFT)
tk.Radiobutton(lfExposure_mode2, variable=varExposureMode,
        text='fireworks',value='fireworks',command=cmdEposureMode).pack(
            anchor=tk.W, side=tk.LEFT)
#==========================================================
#common button handler for ImageEffect without parameter setting,
#simple set camera.image_effect
def butComImageEffect():
    camera.image_effect=varImageEffect.get()
    labelImageEffectVar.set(camera.image_effect)

#----- ImageEffect 'solarise' ui event
def butImageEffect_solarize():
    camera.image_effect=varImageEffect.get()
    if cbSolarize_yuv_Var.get():
        yuv = 1
    else:
        yuv = 0
    solarize_para = (yuv,
                     scSolarize_x0_Var.get(),
                     scSolarize_y0_Var.get(),
                     scSolarize_y1_Var.get(),
                     scSolarize_y2_Var.get())
    camera.image_effect_params = solarize_para
    labelImageEffectVar.set(camera.image_effect +
                            " " + str(camera.image_effect_params))
    
def ev_solarizePara(new_value=None):
    varImageEffect.set("solarize")
    butImageEffect_solarize()

#----- ImageEffect 'watercolor' ui event ---
def butImageEffect_watercolor():
    camera.image_effect=varImageEffect.get()
    
    if cbWatercolor_uv_Var.get():
        watercolor_para = (scWatercolor_u_Var.get(),
                           scWatercolor_v_Var.get())
        camera.image_effect_params = watercolor_para
    else:
        watercolor_para = ()
        camera.image_effect_params = watercolor_para
    
    labelImageEffectVar.set(camera.image_effect +
                            " " + str(camera.image_effect_params))
    
def ev_watercolorPara(new_value=None):
    varImageEffect.set("watercolor")
    butImageEffect_watercolor()
    
#----- ImageEffect 'film' ui event ---
def butImageEffect_film():
    camera.image_effect=varImageEffect.get()
    
    film_para = (scFilm_strength_Var.get(),
                 scFilm_u_Var.get(),
                 scFilm_v_Var.get())
    camera.image_effect_params = film_para
    
    labelImageEffectVar.set(camera.image_effect +
                            " " + str(camera.image_effect_params))
    
def ev_filmPara(new_value=None):
    varImageEffect.set("film")
    butImageEffect_film()
    
#----- ImageEffect 'blur' ui event ---
def butImageEffect_blur():
    camera.image_effect=varImageEffect.get()
    
    camera.image_effect_params = scBlur_size_Var.get()
    
    labelImageEffectVar.set(camera.image_effect +
                            " " + str(camera.image_effect_params))
    
def ev_blurPara(new_value=None):
    varImageEffect.set("blur")
    butImageEffect_blur()
    
#----- ImageEffect 'colorswap' ui event ---
def butImageEffect_colorswap():
    camera.image_effect=varImageEffect.get()
    
    camera.image_effect_params = cbColorswap_dir_Var.get()
    
    labelImageEffectVar.set(camera.image_effect +
                            " " + str(camera.image_effect_params))
    
def ev_colorswapPara(new_value=None):
    varImageEffect.set("colorswap")
    butImageEffect_colorswap()

#----- ImageEffect 'posterise' ui event ---
def butImageEffect_posterise():
    camera.image_effect=varImageEffect.get()

    camera.image_effect_params = scPosterise_steps_Var.get()

    labelImageEffectVar.set(camera.image_effect +
                            " " + str(camera.image_effect_params))
    
def ev_posterisePara(new_value=None):
    varImageEffect.set("posterise")
    butImageEffect_posterise()

#----- ImageEffect 'colorpoint' ui event ---
def butImageEffect_colorpoint():
    camera.image_effect=varImageEffect.get()

    camera.image_effect_params = quadrantVar.get()
    
    labelImageEffectVar.set(camera.image_effect +
                            " " + str(camera.image_effect_params))
    
def ev_colorpointPara(new_value=None):
    varImageEffect.set("colorpoint")
    butImageEffect_colorpoint()

#----- ImageEffect 'colorbalance' ui event ---
def butImageEffect_colorbalance():
    camera.image_effect=varImageEffect.get()

    colorbalance_para = (scColorbalance_lens_Var.get(),
                         scColorbalance_r_Var.get(),
                         scColorbalance_g_Var.get(),
                         scColorbalance_b_Var.get(),
                         scColorbalance_u_Var.get(),
                         scColorbalance_v_Var.get())
    camera.image_effect_params = colorbalance_para
    
    labelImageEffectVar.set(camera.image_effect +
                            " " + str(camera.image_effect_params))
    
def ev_colorbalancePara(new_value=None):
    varImageEffect.set("colorbalance")
    butImageEffect_colorbalance()
#-----------------------------------------------------
#-----------------------------------------------------
    
# Tab Image Effect
varImageEffect = tk.StringVar()
labelImageEffectVar = tk.StringVar()
image_effect_setting = camera.image_effect
varImageEffect.set(image_effect_setting)
labelImageEffectVar.set(image_effect_setting)
tk.Label(frame3, textvariable=labelImageEffectVar).pack(anchor=tk.N)

#-- image_effect

lfNoParaOpts1 = ttk.Frame(frame3)
lfNoParaOpts1.pack(fill="x", expand="yes", anchor=tk.N)

tk.Radiobutton(lfNoParaOpts1, variable=varImageEffect,
        text='none',value='none',command=butComImageEffect).pack(
            anchor=tk.W, side=tk.LEFT)
tk.Radiobutton(lfNoParaOpts1, variable=varImageEffect,
        text='negative',value='negative',command=butComImageEffect).pack(
            anchor=tk.W, side=tk.LEFT)
tk.Radiobutton(lfNoParaOpts1, variable=varImageEffect,
        text='sketch',value='sketch',command=butComImageEffect).pack(
            anchor=tk.W, side=tk.LEFT)
tk.Radiobutton(lfNoParaOpts1, variable=varImageEffect,
        text='denoise',value='denoise',command=butComImageEffect).pack(
            anchor=tk.W, side=tk.LEFT)
tk.Radiobutton(lfNoParaOpts1, variable=varImageEffect,
        text='emboss',value='emboss',command=butComImageEffect).pack(
            anchor=tk.W, side=tk.LEFT)
tk.Radiobutton(lfNoParaOpts1, variable=varImageEffect,
        text='oilpaint',value='oilpaint',command=butComImageEffect).pack(
            anchor=tk.W, side=tk.LEFT)
tk.Radiobutton(lfNoParaOpts1, variable=varImageEffect,
        text='hatch',value='hatch',command=butComImageEffect).pack(
            anchor=tk.W, side=tk.LEFT)
tk.Radiobutton(lfNoParaOpts1, variable=varImageEffect,
        text='gpen',value='gpen',command=butComImageEffect).pack(
            anchor=tk.W, side=tk.LEFT)

lfNoParaOpts2 = ttk.Frame(frame3)
lfNoParaOpts2.pack(fill="x", expand="yes", anchor=tk.N)
tk.Radiobutton(lfNoParaOpts2, variable=varImageEffect,
        text='pastel',value='pastel',command=butComImageEffect).pack(
            anchor=tk.W, side=tk.LEFT)
tk.Radiobutton(lfNoParaOpts2, variable=varImageEffect,
        text='saturation',value='saturation',command=butComImageEffect).pack(
            anchor=tk.W, side=tk.LEFT)
tk.Radiobutton(lfNoParaOpts2, variable=varImageEffect,
        text='washedout',value='washedout',command=butComImageEffect).pack(
            anchor=tk.W, side=tk.LEFT)
tk.Radiobutton(lfNoParaOpts2, variable=varImageEffect,
        text='cartoon',value='cartoon',command=butComImageEffect).pack(
            anchor=tk.W, side=tk.LEFT)
tk.Radiobutton(lfNoParaOpts2, variable=varImageEffect,
        text='deinterlace1',value='deinterlace1',command=butComImageEffect).pack(
            anchor=tk.W, side=tk.LEFT)
tk.Radiobutton(lfNoParaOpts2, variable=varImageEffect,
        text='deinterlace2',value='deinterlace2',command=butComImageEffect).pack(
            anchor=tk.W, side=tk.LEFT)

lfSolarize = ttk.LabelFrame(frame3, text="solarize")
lfSolarize.pack(fill="x", expand="yes", anchor=tk.N)

tk.Radiobutton(lfSolarize, variable=varImageEffect,
        text='solarize',value='solarize',command=butImageEffect_solarize).pack(
            anchor=tk.W, side=tk.LEFT)

cbSolarize_yuv_Var = tk.BooleanVar()
tk.Checkbutton(lfSolarize, text="yuv",
    variable=cbSolarize_yuv_Var, command=ev_solarizePara).pack(
        anchor=tk.W, side=tk.LEFT)

scSolarize_x0_Var = tk.IntVar()
scSolarize_x0_Var.set(128)
tk.Scale(lfSolarize, from_=0, to=255,
    orient=tk.HORIZONTAL, length=200, label="x0",
    variable=scSolarize_x0_Var, command=ev_solarizePara).pack(
        anchor=tk.W, side=tk.LEFT)

scSolarize_y0_Var = tk.IntVar()
scSolarize_y0_Var.set(128)
tk.Scale(lfSolarize, from_=0, to=255,
    orient=tk.HORIZONTAL, length=200, label="y0",
    variable=scSolarize_y0_Var, command=ev_solarizePara).pack(
        anchor=tk.W, side=tk.LEFT)

scSolarize_y1_Var = tk.IntVar()
scSolarize_y1_Var.set(128)
tk.Scale(lfSolarize, from_=0, to=255,
    orient=tk.HORIZONTAL, length=200, label="y1",
    variable=scSolarize_y1_Var, command=ev_solarizePara).pack(
        anchor=tk.W, side=tk.LEFT)

scSolarize_y2_Var = tk.IntVar()
scSolarize_y2_Var.set(0)
tk.Scale(lfSolarize, from_=0, to=255,
    orient=tk.HORIZONTAL, length=200, label="y2",
    variable=scSolarize_y2_Var, command=ev_solarizePara).pack(
        anchor=tk.W, side=tk.LEFT)

lfwatercolor = ttk.LabelFrame(frame3, text="watercolor")
lfwatercolor.pack(fill="x", expand="yes", anchor=tk.N)
tk.Radiobutton(lfwatercolor, variable=varImageEffect,
        text='watercolor',value='watercolor',command=butImageEffect_watercolor
               ).pack(anchor=tk.W, side=tk.LEFT)

cbWatercolor_uv_Var = tk.BooleanVar()
cbWatercolor_uv_Var.set(False)
tk.Checkbutton(lfwatercolor, text="uv",
    variable=cbWatercolor_uv_Var, command=ev_watercolorPara).pack(
        anchor=tk.W, side=tk.LEFT)

scWatercolor_u_Var = tk.IntVar()
scWatercolor_u_Var.set(0)
tk.Scale(lfwatercolor, from_=0, to=255,
    orient=tk.HORIZONTAL, length=200, label="u",
    variable=scWatercolor_u_Var, command=ev_watercolorPara).pack(
        anchor=tk.W, side=tk.LEFT)
scWatercolor_v_Var = tk.IntVar()
scWatercolor_v_Var.set(0)
tk.Scale(lfwatercolor, from_=0, to=255,
    orient=tk.HORIZONTAL, length=200, label="v",
    variable=scWatercolor_v_Var, command=ev_watercolorPara).pack(
        anchor=tk.W, side=tk.LEFT)

lffilm = ttk.LabelFrame(frame3, text="film")
lffilm.pack(fill="x", expand="yes", anchor=tk.N)
tk.Radiobutton(lffilm, variable=varImageEffect,
        text='film',value='film',command=butImageEffect_film).pack(
            anchor=tk.W, side=tk.LEFT)

scFilm_strength_Var = tk.IntVar()
scFilm_strength_Var.set(0)
tk.Scale(lffilm, from_=0, to=255,
    orient=tk.HORIZONTAL, length=200, label="strength",
    variable=scFilm_strength_Var, command=ev_filmPara).pack(
        anchor=tk.W, side=tk.LEFT)
scFilm_u_Var = tk.IntVar()
scFilm_u_Var.set(0)
tk.Scale(lffilm, from_=0, to=255,
    orient=tk.HORIZONTAL, length=200, label="u",
    variable=scFilm_u_Var, command=ev_filmPara).pack(anchor=tk.W, side=tk.LEFT)
scFilm_v_Var = tk.IntVar()
scFilm_v_Var.set(0)
tk.Scale(lffilm, from_=0, to=255,
    orient=tk.HORIZONTAL, length=200, label="v",
    variable=scFilm_v_Var, command=ev_filmPara).pack(anchor=tk.W, side=tk.LEFT)

lfblur = ttk.LabelFrame(frame3, text="blur")
lfblur.pack(fill="x", expand="yes", anchor=tk.N)
tk.Radiobutton(lfblur, variable=varImageEffect,
        text='blur',value='blur',command=butImageEffect_blur).pack(
            anchor=tk.W, side=tk.LEFT)
scBlur_size_Var = tk.IntVar()
scBlur_size_Var.set(1)
tk.Scale(lfblur, from_=1, to=2,
    orient=tk.HORIZONTAL, length=100, label="size",
    variable=scBlur_size_Var, command=ev_blurPara).pack(anchor=tk.W, side=tk.LEFT)

lfcolorswap = ttk.LabelFrame(frame3, text="colorswap")
lfcolorswap.pack(fill="x", expand="yes", anchor=tk.N)
tk.Radiobutton(lfcolorswap, variable=varImageEffect,
        text='colorswap',value='colorswap',command=butImageEffect_colorswap).pack(
            anchor=tk.W, side=tk.LEFT)
cbColorswap_dir_Var = tk.BooleanVar()
cbColorswap_dir_Var.set(False)
tk.Checkbutton(lfcolorswap, text="dir - 0:RGB to BGR/1:RGB to BRG",
    variable=cbColorswap_dir_Var, command=ev_colorswapPara).pack(
        anchor=tk.W, side=tk.LEFT)

lfposterise = ttk.LabelFrame(frame3, text="posterise")
lfposterise.pack(fill="x", expand="yes", anchor=tk.N)
tk.Radiobutton(lfposterise, variable=varImageEffect,
        text='posterise',value='posterise',command=butImageEffect_posterise).pack(
            anchor=tk.W, side=tk.LEFT)
scPosterise_steps_Var = tk.IntVar()
scPosterise_steps_Var.set(4)
tk.Scale(lfposterise, from_=2, to=32,
    orient=tk.HORIZONTAL, length=200, label="steps",
    variable=scPosterise_steps_Var, command=ev_posterisePara).pack(
        anchor=tk.W, side=tk.LEFT)

lfcolorpoint = ttk.LabelFrame(frame3, text="colorpoint")
lfcolorpoint.pack(fill="x", expand="yes", anchor=tk.N)
tk.Radiobutton(lfcolorpoint, variable=varImageEffect,
        text='colorpoint',value='colorpoint',command=butImageEffect_colorpoint).pack(
            anchor=tk.W, side=tk.LEFT)
quadrantVar = tk.IntVar()
quadrantVar.set(0)
tk.Radiobutton(lfcolorpoint, text="green",
    variable=quadrantVar, value=0, command=ev_colorpointPara).pack(
        anchor=tk.W, side=tk.LEFT)
tk.Radiobutton(lfcolorpoint, text="red/yellow",
    variable=quadrantVar, value=1, command=ev_colorpointPara).pack(
        anchor=tk.W, side=tk.LEFT)
tk.Radiobutton(lfcolorpoint, text="blue",
    variable=quadrantVar, value=2, command=ev_colorpointPara).pack(
        anchor=tk.W, side=tk.LEFT)
tk.Radiobutton(lfcolorpoint, text="purple",
    variable=quadrantVar, value=3, command=ev_colorpointPara).pack(
        anchor=tk.W, side=tk.LEFT)

lfcolorbalance = ttk.LabelFrame(frame3, text="colorbalance: I can't see any effect!")
lfcolorbalance.pack(fill="x", expand="yes", anchor=tk.N)
tk.Radiobutton(lfcolorbalance, variable=varImageEffect,
        text='colorbalance',value='colorbalance',command=butImageEffect_colorbalance).pack(
            anchor=tk.W, side=tk.LEFT)

scColorbalance_lens_Var = tk.DoubleVar()
scColorbalance_lens_Var.set(0)
tk.Scale(lfcolorbalance, from_=0, to=256,
    orient=tk.HORIZONTAL, length=140, label="lens",
    variable=scColorbalance_lens_Var, command=ev_colorbalancePara).pack(
        anchor=tk.W, side=tk.LEFT)

scColorbalance_r_Var = tk.DoubleVar()
scColorbalance_r_Var.set(1)
tk.Scale(lfcolorbalance, from_=0, to=256,
    orient=tk.HORIZONTAL, length=140, label="r",
    variable=scColorbalance_r_Var, command=ev_colorbalancePara).pack(
        anchor=tk.W, side=tk.LEFT)

scColorbalance_g_Var = tk.DoubleVar()
scColorbalance_g_Var.set(1)
tk.Scale(lfcolorbalance, from_=0, to=256,
    orient=tk.HORIZONTAL, length=140, label="g",
    variable=scColorbalance_g_Var, command=ev_colorbalancePara).pack(
        anchor=tk.W, side=tk.LEFT)

scColorbalance_b_Var = tk.DoubleVar()
scColorbalance_b_Var.set(1)
tk.Scale(lfcolorbalance, from_=0, to=256,
    orient=tk.HORIZONTAL, length=140, label="b",
    variable=scColorbalance_b_Var, command=ev_colorbalancePara).pack(
        anchor=tk.W, side=tk.LEFT)

scColorbalance_u_Var = tk.IntVar()
scColorbalance_u_Var.set(0)
tk.Scale(lfcolorbalance, from_=0, to=255,
    orient=tk.HORIZONTAL, length=140, label="u",
    variable=scColorbalance_u_Var, command=ev_colorbalancePara).pack(
        anchor=tk.W, side=tk.LEFT)

scColorbalance_v_Var = tk.IntVar()
scColorbalance_v_Var.set(0)
tk.Scale(lfcolorbalance, from_=0, to=255,
    orient=tk.HORIZONTAL, length=140, label="v",
    variable=scColorbalance_v_Var, command=ev_colorbalancePara).pack(
        anchor=tk.W, side=tk.LEFT)

#==========================================================
root.mainloop()

print("- bye -")


Remark:
As this is writing, picamera is still 1.13, so the maximum resolution is 3280x2464 for V2, not HQ. 



~ Another minimum version:  with minimum functions preview and capture only, using PyQt5 GUI, fixed resolution 240x240, and display the captured image on GUI. You can also choice save file name; image.jpg or img_<timestamp>.jpg, under Desktop folder.

Related:

Friday, January 1, 2021

Raspberry Pi stream camera video using raspivid in rtsp protocol, view in Android using VLC app.

Work on Raspberry Pi 4B/8G running Raspberry Pi OS (32 bit), stream video from Camera Module to port 8000 in rtsp protocol, enter the command:

$ raspivid -o - -t 0 -n -w 800 -h 600 -fps 30| cvlc -vvv stream:///dev/stdin --sout '#rtp{sdp=rtsp://:8000/}' :demux=h264

where:
-w 800 : width=800
-h 600 : height=600
-fps 30 : 30 frame per second
8000 : the port to stream video

Open VLC App, Open Network Stream
rtsp://<Raspberry Pi IP>:8000/
e.g. rtsp://192.168.1.30:8000/

Thursday, February 7, 2019

Raspberry Pi: Stream video to VLC player, using rtsp protocol.

Stream Camera Module video to network and play the streaming video using VLC player, using rtsp protocol.


In this video:
I enter Raspberry Pi command via VNC Viewer running on Windows 10 to control Raspberry Pi Zero W with VNC enabled, to stream camera video to network using rtsp protocol. In PC side, view the streaming video using VLC Media Player.

In Raspberry Pi side:
Setup under test:
board: Raspberry Pi Zero W
Camera Module: Raspberry Pi Camera Rev 1.3
OS: Raspbian Stretch with desktop and recommended software, release 2018-11-13

Enter the command:
$raspivid -o - -t 0 -n -w 320 -h 240 -fps 30| cvlc -vvv stream:///dev/stdin --sout '#rtp{sdp=rtsp://:8000/}' :demux=h264

where
-w 320 : width=320
-h 240 : height=240
-fps 30 : 30 frame per second
8000 : the port to stream video

PC side:
OS: Windows 10
Player: VLC Media Player 3.0.6

Open VLC Media Player, click Media > Open Network Stream... > Select Network tab, enter: rtsp://192.168.1.13:8000/

where
192.168.1.13 : the IP of the Raspberry Pi
8000 : the streaming port set at Raspberry Pi side


Tested again@2021-01-01:

Friday, January 25, 2019

Cloned Raspberry Pi Camera Rev 1.3

I bought a camera module form a China on-line shop for a unreasonable low price of RMB 27.70. There are no any certification marking printed on board. I think it's a CLONED Raspberry Pi Camera Rev 1.3.






It was shipped in a white-box package.


Compare with old photos of My Raspberry Pi Camera Modules.

Test shot:




Thursday, June 8, 2017

Mount Raspberry Pi Camera Module to telescope (with sample video of the Moon)

This video show how to connect Raspberry Pi NoIR Camera Module V2 to telescope, with sample video of the Moon at the end of the video.


Parts:
- Raspberry Pi Camera Module (NoIR V2 shown in the video), with original lens removed.
Caution, removing the lens will void your warranty of the camera module.

- CCTV M12 (or S-mount) housing.
Plastic type, have to cut a little bit as shown:


Normally, the center-to-center distance of the mounting holes is 20mm or 22mm, it cannot be installed on Raspberry Pi Camera Module directly. I mount it with one screw on one hole, and fix it with cable tie on the another hole.

- M12 adapter for telescope.
May be it's the most difficult find parts. It have to mach with your telescope.

- Telescope
It's a 10+ years old small telescope (Bosma D = 90mm / f = 1200mm f/13.3)










Related:
Saturn@Raspberry Pi NoIR Camera V2/Nikkor AF 300mm f4
The Moon and Saturn@RPi NoIR Camera V2/Nikkor AF 300mm f4 - 2017-06-08


Wednesday, June 7, 2017

The Moon and Saturn@RPi NoIR Camera V2/Nikkor AF 300mm f4 - 2017-06-08

Videos of The Moon and Saturn, by Raspberry Pi NoIR Camera V2 with Nikkor AF 300mm f4, at 2017-06-08.




For the setup, refer to the post "Saturn@Raspberry Pi NoIR Camera V2/Nikkor AF 300mm f4".

reminder:
Saturn is approaching opposite the Sun, at 15 Jun 2017.

This optimal positioning occurs when Saturn is almost directly opposite the Sun in the sky. Since the Sun reaches its greatest distance below the horizon at midnight, the point opposite to it is highest in the sky at the same time.

At around the same time that Saturn passes opposition, it also makes its closest approach to the Earth – termed its perigee – making it appear at its brightest and largest.

in-the-sky.org - Saturn at opposition


Related:
Mount Raspberry Pi Camera Module to telescope (with sample video of the Moon)

Sunday, July 24, 2016

Saturn@Raspberry Pi NoIR Camera V2/Nikkor AF 300mm f4



Saturn photo and video by Raspberry Pi NoIR Camera V2 x Nikkor AF 300mm f4, connected with Canon EF Lens adapter for Raspberry Pi and Nikon-EOS adapter.


Remark about aperture:
Most modern lens have aperture controlled by camera body, no aperture ring on lens body. The aperture is set minimum without camera. So, make sure your lens have manual aperture control on lens body.

More:
The Moon and Saturn@RPi NoIR Camera V2/Nikkor AF 300mm f4 - 2017-06-08

Related:
Saturn, Jupiter & Mars@WaveShare Pi Camera/Nikkor AF 300mm f4
The Moon@WaveShare Pi Camera/Nikkor AF 300mm f4
Mount Raspberry Pi Camera Module to telescope (with sample video of the Moon)


Thursday, July 21, 2016

Saturn, Jupiter & Mars@WaveShare Pi Camera/Nikkor AF 300mm f4

Photos and video of Saturn, Jupiter & Mars, by WaveShare Pi Camera/Nikkor AF 300mm f4. Not too good, just a trial.

Saturn

Jupiter

Mars


Gears:
- WaveShare Raspberry Pi Camera Module: It's a made in China Raspberry Pi Camera Module using the same 5-megapixel sensor of Official Raspberry Pi Camera Module 1.3, OV5647. But with a easy replace lens housing.
- CS Lens housing, to replace the original lens housing of the Camera Module, to change it to CS-mount. (The original house is M12 mount)
- AI-CS adapter, to connect Nikon (or Nikkor) lens to CS mount.
- Nikkor AF 300mm f4 ED tele lens.






Related:
Pi telecamera - WaveShare Raspberry Pi Camera module connect to 300mm tele lens
The Moon, by Pi telecamera
Saturn@Raspberry Pi NoIR Camera V2/Nikkor AF 300mm f4

Thursday, July 14, 2016

Pi telecamera - WaveShare Raspberry Pi Camera module connect to 300mm tele lens



This post show how to build a Raspberry Pi Telescope using:
- Nikkor AF 300mm f4 ED
- AI-C mount adapter (Nikkor Lens to C-mount)
- C-M12
- WaveShare Raspberry Pi Camera Module

Why use WaveShare Camera Module, not official?
Because WaveShare Camera Module build with M12 mount, come with removable fisheye lens. It's easy to connect to any DSLR lens with adapter.




Here show the resulting photos:




Compare with the photo by the same lens (Nikkor AF 300mm f4 ED) on Nikon DSLR D700


More samples:
- The Moon
Saturn, Jupiter & Mars

Thursday, July 7, 2016

Waveshare Raspberry pi Camera Module with Fisheye Lens (video and photo samples)


  • It's not official Raspberry pi Camera Module.
  • It's Waveshare Raspberry pi Camera Module with Fisheye Lens/5 MP OV5647 Sensor/adjustable focus length, compatible wih Raspberry Pi Camera Module.









The center-to-center distance of the mounting holes is ~20mm, It's easy to find replacement of m-12 mount or c/cs-mount. The official Raspberry Pi Camera Module is ~21mm,

Related:
Pi telecamera - WaveShare Raspberry Pi Camera module connect to 300mm tele lens


Related:
No brand made in China Raspberry Pi NoIR Camera Module

Wednesday, July 6, 2016

raspistill error while loading shared libraries: libbrcmGLESv2.so

Today, I re-install Raspberry Pi 2 with Raspbian Jessie, and update software/firmware:
$ sudo apt update
$ sudo apt upgrade
$ sudo rpi-update

And try to take still photo using raspistill, error reported while loading libbrcmGLESv2.so:
raspistill: error while loading shared libraries: libbrcmGLESv2.so: cannot open shared object file: No such file or directory


But I still can take photos using Python.

I still can record video using raspivid, but cannot play with omxplayer, with error of:
/usr/bin/omxplayer.bin: error while loading shared libraries: libbrcmGLESv2.so: cannot open shared object file: No such file or directory


I guest it is related to updated firmware. Anybody know how?


Updated@2016-07-07: This problem self-fixed by updating firmware with:
$ sudo rpi-update

Monday, June 27, 2016

picamera updated 1.11


Picamera updated 1.11, now support Camera V2. If you not yet updated, run the command to update:
$ sudo apt-get update
$ sudo apt-get upgrade

Suggested to update firmware also:
$ sudo rpi-update


Release 1.11 (2016-06-19) Change log (https://picamera.readthedocs.io/en/release-1.11/changelog.html):

1.11 on the surface consists mostly of enhancements, but underneath includes a major re-write of picamera’s core:

  • Direct capture to buffer-protocol objects, such as numpy arrays (#241)
  • Add request_key_frame() method to permit manual request of an I-frame during H264 recording; this is now used implicitly by split_recording() (#257)
  • Added timestamp attribute to query camera’s clock (#212)
  • Added framerate_delta to permit small adjustments to the camera’s framerate to be performed “live” (#279)
  • Added clear() and copy_to() methods to PiCameraCircularIO (#216)
  • Prevent setting attributes on the main PiCamera class to ease debugging in educational settings (#240)
  • Due to the core re-writes in this version, you may require cutting edge firmware (sudo rpi-update) if you are performing unencoded captures, unencoded video recording, motion estimation vector sampling, or manual sensor mode setting.
  • Added property to control preview’s resolution separately from the camera’s resolution (required for maximum resolution previews on the V2 module - #296).

There are also several bug fixes:

  • Fixed basic stereoscopic operation on compute module (#218)
  • Fixed accessing framerate as a tuple (#228)
  • Fixed hang when invalid file format is specified (#236)
  • Fixed multiple bayer captures with capture_sequence() and capture_continuous() (#264)
  • Fixed usage of “falsy” custom outputs with motion_output (#281)
Many thanks to the community, and especially thanks to 6by9 (one of the firmware developers) who’s fielded seemingly endless questions and requests from me in the last couple of months!


Hardware Limits (http://picamera.readthedocs.io/en/release-1.11/fov.html#hardware-limits):

The are additional limits imposed by the GPU hardware that performs all image and video processing:

  • The maximum resolution for MJPEG recording depends partially on GPU memory. If you get “Out of resource” errors with MJPEG recording at high resolutions, try increasing gpu_mem in /boot/config.txt.
  • The maximum horizontal resolution for default H264 recording is 1920. Any attempt to recording H264 video at higher horizontal resolutions will fail.
  • However, H264 high profile level 4.2 has slightly higher limits and may succeed with higher resolutions.
  • The maximum resolution of the V2 camera can cause issues with previews. Currently, picamera runs previews at the same resolution as captures (equivalent to -fp in raspistill). You may need to increase gpu_mem in /boot/config.txt to achieve full resolution operation with the V2 camera module.
  • The maximum framerate of the camera depends on several factors. With overclocking, 120fps has been achieved on a V2 module but 90fps is the maximum supported framerate.
  • The maximum exposure time is currently 6 seconds on the V1 camera module, and 10 seconds on the V2 camera module. Remember that exposure time is limited by framerate, so you need to set an extremely slow framerate before setting shutter_speed.