{"id":3489,"date":"2020-10-25T21:57:04","date_gmt":"2020-10-25T21:57:04","guid":{"rendered":"http:\/\/www.amzsaki.com\/?page_id=3489"},"modified":"2020-10-25T22:09:25","modified_gmt":"2020-10-25T22:09:25","slug":"blackbirch-camera-app-python-code","status":"publish","type":"page","link":"https:\/\/www.amzsaki.com\/?page_id=3489","title":{"rendered":"blackBirch camera app &#8211; Python code"},"content":{"rendered":"\n<p><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import tkinter as tk\nimport tkinter.ttk as ttk\nfrom tkinter import font\nfrom time import sleep\nfrom picamera import PiCamera\nimport math\nfrom io import BytesIO\nfrom PIL import Image, ImageTk, ImageOps, ImageColor\nimport serial\nimport time\nfrom datetime import datetime\nimport os\nimport tkinter.messagebox\n\n# font and size for labels\nstandardFont=\"DejaVu Sans\"\nstandardFontSize=16\n\n\n# possible shutter speed values (in milliseconds and in seconds)\nshutterSpeedValues=&#91;200,500,1000,2000,4000,8000,16666,33333,66666,125000,250000,500000,1000000,2000000,4000000,6000000]\nshutterSpeedValuesText=&#91;\"1\/5000\",\"1\/2000\",\"1\/1000\",\"1\/500\",\"1\/250\",\"1\/125\",\"1\/60\",\"1\/30\",\"1\/15\",\"1\/8\",\"1\/4\",\"1\/2\",\"1\",\"2\",\"4\",\"6\"]\n\n# possible focus preview values (in seconds)\nfocusPreviewTimeValues=&#91;1,5,10,20,30]\nfocusPreviewTimeValuesText=&#91;\"1\",\"5\",\"10\",\"20\",\"30\"]\n\n# filenames and folders\nfileName=\"frame\"\nfileNameFullGlobal=\"\"\nfileFolder=\"capture\/\"\n\nglobal previewImage\n\n# preview image size and location\nxPreviewSize=466 \nyPreviewSize=350\nxPreviewStart=5\nyPreviewStart=90\nxPreviewEnd=xPreviewStart+xPreviewSize\nyPreviewEnd=yPreviewStart+yPreviewSize\n\n\n# access to camera via PiCamera\ncamera=PiCamera()\n# full resolution for the 5MP camera\ncamera.resolution=(2592,1944)\n\n\n# callback for mouse click\ndef callback(event):\n    xMouseClicked=event.x\n    yMouseClicked=event.y\n    print (xMouseClicked,yMouseClicked)\n    global xGridCellSelected\n    global yGridCellSelected\n    \ndef drawPreviewImage():\n    print (\"in drawPreviewImage\")\n    canvas.delete(\"all\")\n    \n    global previewImage\n    \n    previewImageOnCanvas=canvas.create_image(xPreviewStart,yPreviewStart,anchor=tk.NW,image=previewImage)\n\n# commands\ndef focusCommand():\n    print (\"in focusCommand\")\n        \n    print (\"focusPreviewTime: \"+str(focusPreviewTime.get()))\n    camera.shutter_speed=shutterSpeedValues&#91;shutterSpeed.current()]\n    print (\"shutterSpeed: \"+str(shutterSpeedValues&#91;shutterSpeed.current()]))\n    \n    camera.start_preview()\n    sleep(focusPreviewTime.get())\n    camera.stop_preview()\n            \ndef captureCommand():\n    print (\"in captureCommand\")\n    \n    global previewImage\n    global previewImagePIL\n    \n    print (shutterSpeedValues&#91;shutterSpeed.current()])\n    stream=BytesIO()\n    camera.shutter_speed=shutterSpeedValues&#91;shutterSpeed.current()]\n \n               \n    # capture image\n    now=datetime.now()\n    dateTime=now.strftime(\"%Y-%m-%d-%H-%M-%S\")\n    fileNameFull=fileName+\"_\"+dateTime\n    global fileNameFullGlobal\n    fileNameFullGlobal=fileNameFull\n    print(\"raspi captured image: \"+fileNameFull)\n                \n    camera.capture(stream,format='jpeg')\n    stream.seek(0)\n    image=Image.open(stream)\n    image.save(fileFolder+fileNameFull+\".jpg\",\"JPEG\")\n\n    # generate the preview image\n    size=466,350\n    image.thumbnail(size,Image.ANTIALIAS)\n            \n    previewImage=ImageTk.PhotoImage(image)\n            \n    # need to redraw preview image\n    drawPreviewImage()\n           \n    # refresh the window\n    root.update()\n            \n    \ndef histogramCommand():\n    print (\"in histogramCommand\")\n\n    print (fileNameFullGlobal+\".jpg\")\n    \n    commandString=\"cd \"+fileFolder+\";\"+\"convert \"+fileNameFullGlobal+\".jpg\"+\" -define histogram:unique-colors=false histogram:histogram.gif\"\n    os.system(commandString)\n    commandString=\"cd \"+fileFolder+\";\"+\"convert histogram.gif -resize 466x350 \"+fileNameFullGlobal+\"_hist.png\"\n    os.system(commandString)\n    \n    print (fileNameFullGlobal+\"_hist.png\")\n    \n    imHist=Image.open(fileFolder+fileNameFullGlobal+\"_hist.png\")\n    \n    global previewImage\n    \n    previewImage=ImageTk.PhotoImage(imHist)\n            \n    # need to redraw preview image\n    drawPreviewImage()\n    \n    \n\ndef frameavgCommand():\n    print (\"in frameavgCommand\")\n    print (frameavgNumber.get())\n    \n    now=datetime.now()\n    dateTime=now.strftime(\"%Y-%m-%d-%H-%M-%S\")\n    \n    currentFANumber=1\n    \n    currentFANumberLabel=tk.Label(root,bg=\"black\",fg=\"white\",text=str(currentFANumber))\n    currentFANumberLabel.place(x=520,y=330)\n    currentFANumberLabel.config(font=(standardFont,standardFontSize))\n    \n    for fa in range(frameavgNumber.get()):\n        \n        currentFANumber=fa+1\n        currentFANumberLabel.configure(text=str(currentFANumber))\n        \n        canvas.update_idletasks()\n        \n        stream=BytesIO()\n        camera.shutter_speed=shutterSpeedValues&#91;shutterSpeed.current()]\n            \n        camera.capture(stream,format='jpeg')\n        stream.seek(0)\n        image=Image.open(stream)\n        image.save(fileFolder+\"fa_\"+dateTime+\"_\"+str(fa)+\".jpg\",\"JPEG\")\n     \n    currentFANumberLabel.configure(text=\"P\")\n    canvas.update_idletasks()\n    \n    fileNameFull=fileName+\"_\"+dateTime\n    global fileNameFullGlobal\n    fileNameFullGlobal=fileNameFull+\"_fa\"\n    \n    commandString=\"cd \"+fileFolder+\";\"+\"convert fa_\"+dateTime+\"_*\"+\" -evaluate-sequence mean \"+fileNameFull+\"_fa.jpg\"\n    os.system(commandString)\n    \n    imFa=Image.open(fileFolder+fileNameFull+\"_fa.jpg\")\n    \n    size=466,350\n    imFa.thumbnail(size,Image.ANTIALIAS)\n                \n    global previewImage\n    \n    previewImage=ImageTk.PhotoImage(imFa)\n            \n    # need to redraw preview image\n    drawPreviewImage()\n    \n    currentFANumberLabel.configure(text=\"\")\n    canvas.update_idletasks()\n\n    print (\"done frameaveraging\")\n    \n    \ndef blackBirchCommand():\n    print (\"in blackBirchCommand\")\n    \n    tk.messagebox.showinfo(\"About\",\"blackBirch camera\\ncontrol software\\nA.M. Zsaki\\nattila@amzsaki.com\")\n    \n    \n\nroot=tk.Tk()\nroot.geometry(\"540x450+0+0\")\nroot.title(\"blackBirch\")\n\nstandardFontDefined=font.Font(family=standardFont,size=standardFontSize)\nroot.option_add(\"*Font\",standardFontDefined)\n\ncanvas=tk.Canvas(root,bg=\"black\",width=540,height=450)\ncanvas.bind(\"&lt;Button-1>\",callback)\ncanvas.pack()\n\nshutterSpeedLabel=tk.Label(root,bg=\"black\",fg=\"white\",text=\"Shutter Speed (s)\")\nshutterSpeedLabel.place(x=5,y=1)\nshutterSpeedLabel.config(font=(standardFont,standardFontSize))\nshutterSpeedCurrentValue=0\nshutterSpeed=ttk.Combobox(root,textvariable=shutterSpeedCurrentValue,values=shutterSpeedValuesText,exportselection=0)\nshutterSpeed.place(x=5,y=50)\nshutterSpeed.config(font=(standardFont,standardFontSize))\nshutterSpeed.current(5)\n\nfocusPreviewTimeLabel=tk.Label(root,bg=\"black\",fg=\"white\",text=\"Preview (s)\")\nfocusPreviewTimeLabel.place(x=310,y=1)\nfocusPreviewTimeLabel.config(font=(standardFont,standardFontSize))\nfocusPreviewTime=tk.Scale(root,bg=\"black\",fg=\"white\",from_=5,to=20,tickinterval=0,orient=tk.HORIZONTAL,resolution=5)\nfocusPreviewTime.set(5)\nfocusPreviewTime.place(x=310,y=30)\n\nfocusIcon=tk.PhotoImage(file=\"icons\/focus_45_45.gif\")\nfocusButton=tk.Button(root,image=focusIcon,width=45,height=45,command=focusCommand)\nfocusButton.place(x=480,y=90)\nfocusButton.config(font=(standardFont,standardFontSize))\n\ncaptureIcon=tk.PhotoImage(file=\"icons\/capture_45_45.gif\")\ncaptureButton=tk.Button(root,image=captureIcon,width=45,height=45,command=captureCommand)\ncaptureButton.place(x=480,y=150)\ncaptureButton.config(font=(standardFont,standardFontSize))\n\nhistogramIcon=tk.PhotoImage(file=\"icons\/histogram_45_45.gif\")\nhistogramButton=tk.Button(root,image=histogramIcon,width=45,height=45,command=histogramCommand)\nhistogramButton.place(x=480,y=210)\nhistogramButton.config(font=(standardFont,standardFontSize))\n\nframeavgIcon=tk.PhotoImage(file=\"icons\/frameavg_45_45.gif\")\nframeavgButton=tk.Button(root,image=frameavgIcon,width=45,height=45,command=frameavgCommand)\nframeavgButton.place(x=480,y=270)\nframeavgButton.config(font=(standardFont,standardFontSize))\n\nframeavgNumber=tk.Scale(root,bg=\"black\",fg=\"white\",from_=1,to=8,tickinterval=0,orient=tk.VERTICAL,resolution=1)\nframeavgNumber.set(1)\nframeavgNumber.place(x=480,y=330)\n\npreviewImagePIL=Image.open(\"black_background.gif\")\npreviewImage=ImageTk.PhotoImage(previewImagePIL)\npreviewImageOnCanvas=canvas.create_image(xPreviewStart,yPreviewStart,anchor=tk.NW,image=previewImage)\n\nblackBirchIcon=tk.PhotoImage(file=\"icons\/blackBirchIcon_45_45.gif\")\nblackBirchButton=tk.Button(root,image=blackBirchIcon,width=45,height=45,command=blackBirchCommand)\nblackBirchButton.place(x=480,y=30)\nblackBirchButton.config(font=(standardFont,standardFontSize))\n\n\nroot.mainloop()<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"","protected":false},"author":1,"featured_media":0,"parent":3467,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-3489","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/www.amzsaki.com\/index.php?rest_route=\/wp\/v2\/pages\/3489","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.amzsaki.com\/index.php?rest_route=\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/www.amzsaki.com\/index.php?rest_route=\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/www.amzsaki.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.amzsaki.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=3489"}],"version-history":[{"count":1,"href":"https:\/\/www.amzsaki.com\/index.php?rest_route=\/wp\/v2\/pages\/3489\/revisions"}],"predecessor-version":[{"id":3490,"href":"https:\/\/www.amzsaki.com\/index.php?rest_route=\/wp\/v2\/pages\/3489\/revisions\/3490"}],"up":[{"embeddable":true,"href":"https:\/\/www.amzsaki.com\/index.php?rest_route=\/wp\/v2\/pages\/3467"}],"wp:attachment":[{"href":"https:\/\/www.amzsaki.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=3489"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}