zoukankan      html  css  js  c++  java
  • [原创]-python实用小工具之camera tuning小助手

      最近一直在忙,好久没有上博客园更新文章。趁着有空,将近期用python实现的一个小工具发布出来。这个是本人在实际的工作当中,为了提高效率而开发的一个小工具。正所谓"麻雀虽小,五脏俱全”,虽然是一个简单的小工具,也包含了很多的知识点在里面,也当是这段时间接触python的一次小结吧。与此同时,后期还会不断的完善,该版本只是一个雏形,仅仅实现了最基本的功能,还有很多的地方不是很完善,所以后期会不断的更新。


    需求:

      本人从事camera影像调试的工作,在高通平台下tuning手机摄像头模组。在实际的工作当中,发现有很多拍摄RAW图的时间比较繁琐,而且很多是重复的操作,特别是客观调试的时候,场景基本上都是固定了,但是我们每次去拍照的时候,需要在一个场景下拍图,然后把RAW图导出来,同时更改文件名。很多老练的工程师,都已经习惯了,一个一个的拍,然后改名,放到不同的文件夹下面,中间又需要不断地敲命令导出raw图。可想而知,如果项目的周期很赶,那么使用手动的方式,效率上会浪费比较多的时间,而且容易乱。本人又比较懒,同时又发现了这其中有很多操作是重复的,所以就打算自己写一个工具,来实现大部分的工作,这样就可以节省了比较多的时间,用于真正的分析重要问题上面。

    需求分析:

      既然我们已经知道了要做什么事情,就需要不断地去需求摸清楚,然后选择合适的工具去实现。由于实际的工作又比较简单,用脚本的方式是最容易思实现的,并且不需要编译啥的,即使换一台机器,在相同的操作系统下面仍然能用,省去了很多的麻烦。最开始是使用脚本的方式,比较简单,代码很少,如下:

    @echo off
    rem 在运行该脚本前,请先打开手机的骁龙相机,并设置相应的RAW图开关
    rem ============================================================== 
    
    rem 下面两个路径是手机中Raw图的存放位置,和pull出来的raw存放路径,请检查
    set PHONE_JPG_PATH=sdcard/DCIM/Camera/
    set PHONE_RAW_PATH=sdcard/DCIM/Camera/raw/
    set PULL_RAW_PATH=./raw/
    rem echo PHONE_RAW_PATH=%PHONE_RAW_PATH%
    rem echo PULL_RAW_PATH=%PULL_RAW_PATH%
    rem =============================================================== 
    adb wait-for-device
    adb root
    adb wait-for-device
    adb remount
    
    rem 打开骁龙相机
    rem adb shell am start -a android.media.action.STILL_IMAGE_CAMERA
    rem num27表示的是执行拍照动作
    adb shell input keyevent 27
    rem ================================================================
    rem 修改颜色 color 03
    echo 请稍等
    ping -n 6 127.1 >nul
    echo 开始导出RAW文件
    adb pull sdcard/DCIM/Camera/raw/ ./raw/
    adb shell rm /sdcard/DCIM/Camera/raw/*.raw  
    adb pull %PHONE_RAW_PATH% %PULL_RAW_PATH%
    rem ren %PULL_RAW_PATH%/*.raw %PULL_RAW_PATH%/%1_Lux.raw
    
    echo 删除phone中的RAW图成功! 
    View Code

       但是实际使用的效果,不太好,仍然需要输入很多的命令,并且切换多个目录,一不小心就出错了,浪费比较多的时间。所以就打算进一步的改善。刚好了解到了python,学了一段时间,然后渐渐改良了原来的版本。 

    目前实现的效果:

      

      

     代码如下:

      1 # -*- coding: utf-8 -*-
      2 # ---------------------------------------------------------------------------
      3 # tuning capure pic tools
      4 # This is a free software .
      5 #
      6 # Author: Qibaowei
      7 # Bug report:  
      8 # ---------------------------------------------------------------------------
      9 #
     10 # Function:
     11 #   capure the image to local path
     12 # Version:
     13 #   V1.0 (python 3.7)
     14 # Usage:
     15 #   v1.pyw  
     16 # Example:
     17 #   v1.pyw
     18 
     19 
     20 try:
     21     import tkinter as tk
     22     import tkinter.messagebox
     23     from tkinter import scrolledtext 
     24     from tkinter import ttk
     25 except:
     26     print ('Following module is needed:')
     27     print ('- Tkinter: check the python -v and ensure the version is py3.x')
     28     sys.exit()
     29 
     30 # cmd所依赖的系统库
     31 import os
     32 import time
     33 import re
     34 
     35 # 当配置栏为空时,注意弹出窗口,并且提示。
     36 # 同时配置栏更改时也需要弹出提示窗口
     37 
     38 # 配置路径
     39 RawPath = "sdcard/DCIM/Camera/raw/"
     40 JpgPath = "sdcard/DCIM/Camera/"
     41 SavePicPath = "./raw/"
     42 
     43 # 下拉列表中的值
     44 gScenceValue=['BLC','Rollof','MCC','18%Gray','ISO12233','GrayStep','Flat Field' ]
     45 gLightValue =['A','H','TL84','CWF','U30','D50','D65','D75','LED','Flash','outdoor']
     46 gLuxValue   =[10,20,50,100,200,400,500,1000,'Normal','Low']
     47 gFormatValue=['raw','jpg']
     48 
     49 SavePicName = ' '
     50 ChosenType = 0
     51 ###########################################################################################
     52 class Setting:
     53     def __init__(self,root):
     54         global RawPath
     55         global JpgPath
     56         global SavePicPath
     57         
     58         self.lf_setting = tk.LabelFrame(root, width=240, height=320,text='配置',fg='Tomato')
     59         self.lf_setting.grid(columnspan=3,row=0, column=0, sticky='N'+'S'+'W'+'E',padx=10, pady=6)
     60 
     61         
     62         local = tk.StringVar()
     63         Raw   = tk.StringVar()
     64         Jpg   = tk.StringVar()
     65 
     66         local.set(SavePicPath)
     67         Raw.set(RawPath)
     68         Jpg.set(JpgPath)
     69         
     70         tk.Label(self.lf_setting,text="手机RAW文件路径").grid(row=0,column=0,sticky='E')
     71         tk.Label(self.lf_setting,text="手机JPG文件路径").grid(row=1,column=0,sticky='E')#第二行
     72         tk.Label(self.lf_setting,text="本地保存路径").grid(row=2,column=0,sticky='E')
     73         self.RawPath  = tk.Entry(self.lf_setting, width=60,bg='PaleGreen',fg='red',textvariable =Raw,state = 'disabled').grid(row=0,column=1)
     74         self.JpgPath  = tk.Entry(self.lf_setting, width=60,bg='PaleGreen',fg='red',textvariable =Jpg,state = 'disabled').grid(row=1,column=1)
     75         self.SavePath = tk.Entry(self.lf_setting, width=60,bg='PaleGreen',fg='red',textvariable =local,state = 'disabled').grid(row=2,column=1)
     76 
     77         
     78         
     79     def GetPhoneRawPath(self):
     80         print(self.RawPath.get())
     81 
     82     def GetPhoneJpgPath(self):
     83         print(self.JpgPath.get())
     84 
     85     def GetSavePicPath(self):
     86         print(self.SavePath.get())
     87         
     88     def work(self):
     89         print('setting tab')
     90 
     91 #######################################################################################
     92 class Scene:
     93     def __init__(self,root):
     94         self.lf_res = tk.LabelFrame(root, width=40, height=20, text='拍摄场景',fg='Maroon')  
     95         self.lf_res.grid(row=1, column=0, sticky='W'+'N'+'E',padx=10, pady=5)
     96         # 场景
     97         self.LbScene = tk.Label(self.lf_res,text="场景").grid(row=0,column=0,sticky='E',padx=10, pady=2)
     98         StSceneSelect = tk.StringVar()
     99         self.CChosen = ttk.Combobox(self.lf_res, width=12, textvariable=StSceneSelect, state='readonly')
    100         self.CChosen['values'] = gScenceValue
    101         #self.CChosen['values'] = ('BLC','Rollof','MCC','18%Gray','ISO12233','GrayStep','Flat Field')     # 设置下拉列表的值
    102         self.CChosen.grid(row=0,column=1)      # 设置其在界面中出现的位置  column代表列   row 代表行
    103         self.CChosen.current(2)    # 设置下拉列表默认显示的值,0为 numberChosen['values'] 的下标值        
    104         self.CChosen.bind("<<ComboboxSelected>>", self.SceneSelect)
    105         
    106         # 光源
    107         self.LbLight = tk.Label(self.lf_res,text="光源").grid(row=1,column=0,sticky='E',padx=10, pady=2)
    108         StLightSelect = tk.StringVar()
    109         self.LightChosen = ttk.Combobox(self.lf_res, width=12,textvariable=StLightSelect, state='readonly')
    110         self.LightChosen['values'] = gLightValue
    111         #self.LightChosen['values'] = ('A','H','TL84','CWF','U30','D50','D65','D75','LED','Flash','outdoor')    
    112         self.LightChosen.grid(row=1,column=1)      
    113         self.LightChosen.current(2)    
    114         self.LightChosen.bind("<<ComboboxSelected>>", self.SceneSelect)
    115         
    116         # 照度
    117         StLux = tk.StringVar()
    118         self.LbLux = tk.Label(self.lf_res,text="照度").grid(row=2,column=0,sticky='E',padx=10, pady=2)
    119         self.LuxChosen = ttk.Combobox(self.lf_res, width=12, textvariable=StLux, state='readonly')
    120         self.LuxChosen['values'] = gLuxValue
    121         #self.LuxChosen['values'] = (10,20,50,100,200,400,500,1000,'Normal','Low') 
    122         self.LuxChosen.grid(row=2,column=1)     
    123         self.LuxChosen.current(0)    
    124         self.LuxChosen.bind("<<ComboboxSelected>>", self.SceneSelect)
    125         
    126         # 格式
    127         StFormat = tk.StringVar()
    128         self.LbFormat = tk.Label(self.lf_res,text="格式").grid(row=3,column=0,sticky='E',padx=10, pady=2)
    129         self.FormatChosen = ttk.Combobox(self.lf_res, width=12, textvariable=StFormat, state='readonly')
    130         self.FormatChosen['values'] = gFormatValue
    131         #self.FormatChosen['values'] = ('raw','jpg')
    132         self.FormatChosen.grid(row=3,column=1)      
    133         self.FormatChosen.current(0)    
    134         self.FormatChosen.bind("<<ComboboxSelected>>", self.SceneSelect)
    135 
    136     def SceneSelect(self,*args):
    137         global SavePicName
    138         global ChosenType
    139         SavePicName = (self.CChosen.get()+'_'+self.LightChosen.get()+'_'+self.LuxChosen.get()+'.'+self.FormatChosen.get())
    140         print (SavePicName)
    141         if self.FormatChosen.get().find("raw") != -1:
    142             ChosenType = 0
    143         else:
    144             ChosenType = 1 
    145         
    146     def work(self):
    147         print('Scene tab')
    148 
    149 #########################################################################################
    150 class Control:
    151     def __init__(self,root):
    152         self.lf_control = tk.LabelFrame(root, width=40, height=20, text='控制',fg='Orange')  
    153         self.lf_control.grid(row=1, column=1, sticky='W'+'N',padx=10, pady=5)
    154 
    155         self.bt_openCamera = tk.Button(self.lf_control,text='打开相机',width=10,height=2 ,command=self.OpoenCamera )
    156         self.bt_openCamera.grid(row=0,column=0,padx=10,pady=20)
    157         
    158         self.bt_CloseCamera = tk.Button(self.lf_control,text='关闭相机',width=10,height=2,command=self.CloseCamera  )
    159         self.bt_CloseCamera.grid(row=1,column=0,padx=10,pady=16)
    160         
    161         self.bt_Capure = tk.Button(self.lf_control,text='拍照',width=10,height=2 ,command=self.CapurePicture )
    162         self.bt_Capure.grid(row=0,column=1,padx=10, pady=16)
    163 
    164         self.bt_ClearCamera = tk.Button(self.lf_control,text='清空图片',width=10,height=2 ,command=self.ClearPicture )
    165         self.bt_ClearCamera.grid(row=1,column=1,padx=5, pady=8)        
    166         self.lf_message = tk.LabelFrame(root, width=100, height=50, text='实时信息',fg='DarkGreen')
    167         self.lf_message.grid(columnspan=3,row=2, column=0, sticky='W'+'E'+'N'+'S',padx=10, pady=5)
    168     
    169         self.yScrollbar = tk.Scrollbar(self.lf_message)
    170         self.yScrollbar.pack(side = 'right', fill = 'y')
    171         self.xScrollbar = tk.Scrollbar(self.lf_message, orient = 'horizontal')# HORIZONTAL 设置水平方向的滚动条,默认是竖直
    172         self.xScrollbar.pack(side = 'bottom', fill = 'x') 
    173         # 创建文本框,wrap 设置不自动换行
    174         self.message_out = tk.Text(self.lf_message, width = 100,
    175                                    bg='Black',fg='DarkViolet',
    176                                    yscrollcommand = self.yScrollbar.set, xscrollcommand = self.xScrollbar.set, wrap = 'none')
    177         self.message_out.pack(anchor='center')
    178         
    179     def OpoenCamera(self):
    180         print ('open camera
    ')
    181         global SavePicName
    182         os.popen("adb remount").read()+'
    '
    183         StOpenCamera = os.popen("adb shell am start -a android.media.action.STILL_IMAGE_CAMERA").read()+'
    '
    184         self.message_out.insert(tkinter.END, StOpenCamera)  # INSERT表示在光标位置插入
    185         self.message_out.see(tkinter.END)
    186         self.message_out.update()
    187         print ('rename '+(SavePicName))
    188     
    189     def CloseCamera(self):
    190         print ('close camera
    ')
    191         StOpenCamera = os.popen("adb shell input keyevent 4").read()+'
    '
    192         self.message_out.insert(tkinter.END, StOpenCamera)
    193         self.message_out.see(tkinter.END)
    194         self.message_out.update()
    195         
    196     def CapurePicture(self):
    197         print ('Capure 
    ')
    198         global RawPath
    199         global JpgPath
    200         global SavePicPath
    201         global SavePicName
    202         global ChosenType        
    203         if ( ChosenType == 0):
    204             StOpenCamera = os.popen("adb shell input keyevent 27").read()+'
    '+os.popen("ping -n 6 127.1 >nul").read()+'
    '+os.popen("adb pull "+RawPath+" "+SavePicPath).read()+'
    '
    205             print("Choosen RAW
    ")
    206         else:
    207             StOpenCamera = os.popen("adb shell input keyevent 27").read()+'
    '+os.popen("ping -n 6 127.1 >nul").read()+'
    '+os.popen("adb pull "+JpgPath+" "+SavePicPath).read()+'
    '
    208             print("Choosen JPG
    ")
    209         self.message_out.insert(tkinter.END, StOpenCamera)
    210         self.message_out.see(tkinter.END)
    211         self.message_out.update()
    212         print ("adb pull "+RawPath+" "+SavePicPath)
    213         for item in os.listdir(SavePicPath):
    214             if (re.match(r"^IMG_d+", item)):
    215                 print (item)
    216                 #newname = re.sub(r"(d+)", "", item)
    217                 try:
    218                     os.renames(SavePicPath+item, SavePicPath+SavePicName)
    219                 except OSError:
    220                     pass
    221                 print ("-->" + SavePicName)
    222         if ( ChosenType == 0):
    223             print (os.popen("adb shell rm "+RawPath+'*.raw')+'
    ')
    224         else:
    225             print (os.popen("adb shell rm "+JpgPath+'*.jpg')+'
    ')
    226         
    227     def ClearPicture(self):
    228         print ('Clear raw in phone 
    ')
    229         g_cmd_out = os.popen("adb remount").read()+'
    '
    230         self.message_out.delete('1.0','end')
    231         
    232     def work(self):
    233         print('setting tab')
    234 
    235 ########################################################################################
    236 class Calculate:
    237     def __init__(self,root):
    238         self.lf_calculate = tk.LabelFrame(root, width=40, height=100, text='计算')  
    239         self.lf_calculate.grid(row=1, column=2, sticky='W'+'N'+'S', pady=5)
    240         
    241     def work(self):
    242         print('Calculate tab')
    243 
    244 #######################################################################################
    245 class Message:
    246     def __init__(self,root):
    247         self.lf_message = tk.LabelFrame(root, width=100, height=50, text='实时信息',fg='DarkGreen')  
    248         self.lf_message.grid(columnspan=3,row=2, column=0, sticky='W'+'E'+'N'+'S',padx=10, pady=5)
    249 
    250         self.yScrollbar = tk.Scrollbar(self.lf_message)
    251         self.yScrollbar.pack(side = 'right', fill = 'y')
    252         self.xScrollbar = tk.Scrollbar(self.lf_message, orient = 'horizontal')# HORIZONTAL 设置水平方向的滚动条,默认是竖直
    253         self.xScrollbar.pack(side = 'bottom', fill = 'x') 
    254         # 创建文本框,wrap 设置不自动换行
    255         self.message_out = tk.Text(self.lf_message, width = 100,
    256                                    bg='Black',fg='DarkViolet',
    257                                    yscrollcommand = self.yScrollbar.set, xscrollcommand = self.xScrollbar.set, wrap = 'none')
    258         self.message_out.pack(anchor='center')
    259 
    260     def TextUpdate(self,text):
    261         print('Text update!
    ')
    262         self.message_out.insert(tkinter.END, text)  
    263         self.message_out.see(tkinter.END)
    264         self.message_out.update()
    265     
    266     def TextClear():
    267         print('Text clear')
    268         self.message_out.delete('1.0','end')
    269         
    270     def work(self):
    271         print('Message tab')
    272 
    273 ###########################################################################################
    274 
    275 root = tk.Tk()
    276 root.title('tuning拍图小助手V1.0')
    277 width = 600
    278 height = 480
    279 screenwidth = root.winfo_screenwidth()  
    280 screenheight = root.winfo_screenheight()  
    281 size = '%dx%d+%d+%d' % (width, height, (screenwidth - width)/2, (screenheight - height)/2)
    282 root.geometry(size) # width*height + pos_x + pos_y
    283 
    284 root.columnconfigure(0, weight=1)
    285 root.rowconfigure(0, weight=1)
    286 
    287 content = tk.Frame(root)
    288 content.grid(column=0, row=0, sticky=('N', 'S', 'E', 'W'))
    289 app = Setting(content)
    290 sence = Scene(content)
    291 control = Control(content)
    292 calculate = Calculate(content)
    293 app.work()
    294 
    295 content.columnconfigure(0, weight=3)
    296 content.columnconfigure(1, weight=3)
    297 content.columnconfigure(2, weight=3)
    298 content.columnconfigure(3, weight=1)
    299 content.rowconfigure(2, weight=1)
    300 
    301 sence.work()
    302 control.work()
    303 calculate.work()
    304 sence.SceneSelect()
    305 
    306 root.mainloop()
    View Code

     后期展望:

      目前只是完成了一个简单的GUI界面,并且一些基本的操作,但是逻辑部分还没有衔接上,然后找BUG优化,美化布局这些,然后打包生成exe文件。

    (未完待续,后续更新!······)

  • 相关阅读:
    Spring Security -- 添加图形验证码(转载)
    Spring Security -- 自定义用户认证(转载)
    pandas agg 后降低df表层
    判断是否有人跟踪车辆的方案
    格隆汇笔记-黄勇演讲
    Mac mysql 忘记root密码的解决方法
    sql 同步2个表中的一个字段数据
    Linux下配置用msmtp和mutt发邮件
    spark StructType的应用,用在处理mongoDB keyvalue
    Idea2018旗舰版破解方法
  • 原文地址:https://www.cnblogs.com/qiabaowei/p/9502836.html
Copyright © 2011-2022 走看看