ImgInfoGeter

config.ini

[db]
DB_HOST = 10.20.1.129
USER = sa
PWD = skcl@2013
DATABASE = CDMTCP

[parameter]
DIRECTORY_PATH = D:/ftp
USING_IMG_COMPLETE = False
MODIFY_LAST_BYTE_RTC = False
TIME_WAIT_FOR_FTP = 60
COFFEE = 0.0005
ROAD_GPS_FILE = roadgps.txt
ROAD_ARC_FILE = arcinfo.txt
DATA_FROM_DB = False

[rename]
MOVE_FILE = True
RENAME_BY_EQUIP = False
CAMERA_EQUIP_FILE = cameraId_equipmentId_table_chengdu.txt
MOVE_FLODER = D:/pics/
RENAME_BY_DATE = D

[merge]
DO_MERGE = True
GROUP_PIC_NUM = 3
MERGE_PICS_PATH = D:/合成图片/




dbManager.py

# -*- coding:gbk -*-
# auther : pdm
# email : ppppdm@gmail.com
import logging
import logging.config
import datetime

try:
    import pyodbc
except:
    print('no module pyodbc, should init first!')

# create logger
logging.config.fileConfig("logging.conf")
logger = logging.getLogger("example")

# global variabls
DB_HOST = '10.20.1.129' # '210.73.152.201'
USER = 'sa'
PWD = 'skcl@2013'
DATABASE = 'CDMTCP'



# ---------------------------------------------- DB API --------------------------------------------------

def get_db_connect():
    db_conn = None
    try:
        db_conn = pyodbc.connect('DRIVER={SQL Server}', host = DB_HOST, user = USER, password = PWD, database = DATABASE)
    except: # not print db execption yet
        logger.debug('init db got an error!')
        print('init db got an error!')
    return db_conn

def close_db_connect(db_conn):
    if db_conn:
        db_conn.close()

# -----------------------------------------------------------------------------------------------------

TIME_DELTA = datetime.timedelta(0, 0, 0, 0, 1)
groupCount = dict()
# 用于判断该张图片是否是组内的第一张图片
def isTheFirstOfGroup(camera_id, backup1, captrue_serial_num, collect_date):
    ret = False
    ginfo = groupCount.get(camera_id)
    if  ginfo == None:
        print('group info none')
        groupCount[camera_id] = (backup1, captrue_serial_num, collect_date)
        ret =  True
    elif ginfo[0] < backup1:
        print('date < group info date')
        groupCount[camera_id] = (backup1, captrue_serial_num, collect_date)
        ret = True
    elif ginfo[1] < captrue_serial_num:
        print('num < group info num')
        groupCount[camera_id] = (ginfo[0], captrue_serial_num, collect_date)
        ret = True
    elif (collect_date - ginfo[2] > TIME_DELTA):
        print('time - group info time > ', TIME_DELTA)
        groupCount[camera_id] = (backup1, captrue_serial_num, collect_date)
        ret = True
    return ret

# store one image infos
def store_pic_infos(infos):
    
    # store to db
    if infos:
        # store to logfile
        logger.debug(infos)
        
        camera_id            = infos.get('MAC', '')
        gps_xN               = infos.get('X', '')
        gps_yN               = infos.get('Y', '')
        direction            = infos.get('DIRECT', '')
        collect_dateN        = infos.get('RTC', '')
        car_id               = infos.get('CAR LICENSE', '')
        license_color        = infos.get('LICENSE COLOR', '')
        captrue_serial_num   = infos.get('SERIAL NUMBER', '')
        recieve_begin_timeN  = infos.get('CREATE TIME', '')
        recieve_timeN        = infos.get('MODIFY TIME', '')
        car_distanceN        = infos.get('CAR DISTENCE', '')
        speedN               = infos.get('SPEED', '')
        backup1              = infos.get('DATE', '')
        picture_name         = infos.get('FILE', '')
        data_direction        = infos.get('FILE SUB PATH', '')
        road                 = infos.get('ROAD', '')
        road_id              = infos.get('ROAD_ID', '')
        No                   = infos.get('NO.', '0')
        No                   = str(int(No))
        
        #print('collect_dateN', collect_dateN)
        
        try:
            collect_dateN = datetime.datetime.strptime(collect_dateN, '%Y%m%d%H%M%S%f')
        except:
            collect_dateN = datetime.datetime.now()
            
        #print('collect_dateN', collect_dateN)
        
        try:
            recieve_begin_timeN = datetime.datetime.strptime(recieve_begin_timeN, '%Y%m%d%H%M%S%f')
        except:
            recieve_begin_timeN = datetime.datetime.now()
        
        try:
            recieve_timeN = datetime.datetime.strptime(recieve_timeN, '%Y%m%d%H%M%S%f')
        except:
            recieve_timeN = datetime.datetime.now()

        create_time = datetime.datetime.now()
        
        #print('picture_name', picture_name)
        
        collect_date = 'collect_date' + No
        recieve_begin_time = 'recieve_begin_time' + No
        recieve_time = 'recieve_time' + No
        gps_x = 'gps_x' + No
        gps_y = 'gps_y' + No
        car_distance = 'car_distance' + No
        speed = 'speed' + No
        
        # change backup1 type to str
        backup1 = backup1.strftime('%Y-%m-%d')
        
        db_conn = get_db_connect()
        if db_conn:
            cur              = db_conn.cursor()
            try:
                if isTheFirstOfGroup(camera_id, backup1, captrue_serial_num, collect_dateN):
                    print(picture_name, 'is the first of group')
                    # change 2013.6.1 
                    if No == '1':
                        recieve_time = 'recieve_time'
                    gps_x = 'gps_x'
                    gps_y = 'gps_y'
                    recieve_picture_nums = 1
                    
                    # 如果是组内的第一张图片,向数据库插入一条新的记录
                    sql = "INSERT INTO LS_pictures(camera_id, data_direction, picture_name, direction, road, road_id, car_id, license_color, captrue_serial_num, recieve_picture_nums, " + \
                                                collect_date + ',' + \
                                                recieve_begin_time + ',' + \
                                                recieve_time + ',' + \
                                                gps_x + ',' + \
                                                gps_y + ',' + \
                                                car_distance + ',' + \
                                                speed + ',' + \
                                                "create_time, backup1) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"
                    logger.debug(sql)
                    
                
                    cur.execute(sql, 
                            (
                            camera_id, 
                            data_direction, 
                            picture_name,
                            direction,
                            road, 
                            road_id, 
                            car_id, 
                            license_color, 
                            captrue_serial_num, 
                            recieve_picture_nums, 
                            collect_dateN, 
                            recieve_begin_timeN, 
                            recieve_timeN, 
                            gps_xN,
                            gps_yN,
                            car_distanceN,
                            speedN, 
                            create_time, 
                            backup1
                            ))
                else:# 组内非第一张图片,更新对应的数据库记录
                    print(picture_name, 'is not the first of group')
                    sql = "UPDATE LS_pictures SET data_direction = data_direction + ',' + ?, picture_name = picture_name + ',' + ?,recieve_picture_nums = recieve_picture_nums + 1," + \
                                                collect_date + '=?,' + \
                                                recieve_begin_time + '=?,' + \
                                                recieve_time+ '=?,' + \
                                                gps_x + '=?,' + \
                                                gps_y + '=?,' + \
                                                car_distance + '=?,' + \
                                                speed + '=? ' + \
                                                "WHERE (camera_id = ?) and (backup1 = ?) and (captrue_serial_num = ?) and ( ? - collect_date1 < ?)"
                    logger.debug(sql)
                    
                    cur.execute(sql, 
                            (
                            data_direction, 
                            picture_name, 
                            collect_dateN, 
                            recieve_begin_timeN, 
                            recieve_timeN, 
                            gps_xN,
                            gps_yN,
                            car_distanceN,
                            speedN,
                            camera_id, 
                            backup1, 
                            captrue_serial_num, 
                            collect_dateN, 
                            str(TIME_DELTA)
                            ))
            except:
                print('db execute error!')
                logger.debug('db execute error! %s', infos)
                logger.error('db execute error! %s', infos)
            
            try:
                db_conn.commit()
            
            except: # just not print db error
                print('db commit error!')
                logger.debug('db commit error! %s', infos)
                logger.error('db commit error! %s', infos)
                
        else:
            # get db connect none
            print('get db connect error!')
            logger.debug('get db connect error! %s', infos)
            logger.error('get db connect error! %s', infos)
        
        close_db_connect(db_conn)
    else:
        logger.debug('info none')
    
    return

fileWatcher.py

# -*- coding:gbk -*-
# auther : pdm
# email : ppppdm@gmail.com

import threading
import os
import time

# using Polling , can work across platform 使用轮询,可以在不同操作系统上使用,当前没有使用该方法
def watchFileChange_cross(path_to_watch, func_handle_change = None):
    before = dict ([(f, None) for f in os.listdir (path_to_watch)])
    while 1:
        time.sleep (5)
        after = dict ([(f, None) for f in os.listdir (path_to_watch)])
        added = [f for f in after if not f in before]
        removed = [f for f in before if not f in after]
        if added: 
            changes = []
            for i in added:
                changes.append((3, os.path.join(path_to_watch, i)))
                print ("Added: ", ", ".join (added))
            t = threading.Thread(target=func_handle_change, args = (changes, ))
            t.start()
        if removed: print( "Removed: ", ", ".join (removed))
        before = after



# if operation system is windows
# Use the FindFirstChangeNotification API
# src from http://timgolden.me.uk/python/win32_how_do_i/watch_directory_for_changes.html
# 当前没有使用该方法
def watchFileChange_2(path_to_watch, func_handle_change = None):
    import win32file
    import win32event
    import win32con
    
    #path_to_watch = os.path.abspath (".")
    
    #
    # FindFirstChangeNotification sets up a handle for watching
    #  file changes. The first parameter is the path to be
    #  watched; the second is a boolean indicating whether the
    #  directories underneath the one specified are to be watched;
    #  the third is a list of flags as to what kind of changes to
    #  watch for. We're just looking at file additions / deletions.
    #
    change_handle = win32file.FindFirstChangeNotification (
      path_to_watch,
      0,
      win32con.FILE_NOTIFY_CHANGE_FILE_NAME
    )
    
    #
    # Loop forever, listing any file changes. The WaitFor... will
    #  time out every half a second allowing for keyboard interrupts
    #  to terminate the loop.
    #
    try:
    
      old_path_contents = dict ([(f, None) for f in os.listdir (path_to_watch)])
      while 1:
        result = win32event.WaitForSingleObject (change_handle, 500)
    
        #
        # If the WaitFor... returned because of a notification (as
        #  opposed to timing out or some error) then look for the
        #  changes in the directory contents.
        #
        if result == win32con.WAIT_OBJECT_0:
          new_path_contents = dict ([(f, None) for f in os.listdir (path_to_watch)])
          added = [f for f in new_path_contents if not f in old_path_contents]
          deleted = [f for f in old_path_contents if not f in new_path_contents]
          if added:
              changes = []
              for i in added:
                changes.append((3, os.path.join(path_to_watch, i)))
                print("Added: ", ", ".join (added))
              t = threading.Thread(target=func_handle_change, args = (changes, ))
              t.start()
          if deleted: 
              print("Deleted: ", ", ".join (deleted))
    
          old_path_contents = new_path_contents
          win32file.FindNextChangeNotification (change_handle)
    
    finally:
      win32file.FindCloseChangeNotification (change_handle)


# Use the ReadDirectoryChanges API
# src from http://timgolden.me.uk/python/win32_how_do_i/watch_directory_for_changes.html

#当前调用该方法,给入的参数是需要侦听的文件夹路径和对新增文件的处理函数
def watchFileChange(path_to_watch, func_handle_change = None):
    import win32file
    import win32con
    
    ACTIONS = {
               1 : "Created",
               2 : "Deleted",
               3 : "Updated",
               4 : "Renamed from something",
               5 : "Renamed to something"
               }
    
    # Thanks to Claudio Grondi for the correct set of numbers
    FILE_LIST_DIRECTORY = 0x0001
    
    #path_to_watch = "."
    hDir = win32file.CreateFile (
        path_to_watch,
        FILE_LIST_DIRECTORY,
        win32con.FILE_SHARE_READ | win32con.FILE_SHARE_WRITE | win32con.FILE_SHARE_DELETE,
        None,
        win32con.OPEN_EXISTING,
        win32con.FILE_FLAG_BACKUP_SEMANTICS,
        None
        )
    
    while 1:
        #
        # ReadDirectoryChangesW takes a previously-created
        # handle to a directory, a buffer size for results,
        # a flag to indicate whether to watch subtrees and
        # a filter of what changes to notify.
        #
        # NB Tim Juchcinski reports that he needed to up
        # the buffer size to be sure of picking up all
        # events when a large number of files were
        # deleted at once.
        #
        results = win32file.ReadDirectoryChangesW (
                                                   hDir,
                                                   1024,
                                                   True,
                                                   win32con.FILE_NOTIFY_CHANGE_FILE_NAME |
                                                   win32con.FILE_NOTIFY_CHANGE_DIR_NAME |
                                                   win32con.FILE_NOTIFY_CHANGE_ATTRIBUTES |
                                                   win32con.FILE_NOTIFY_CHANGE_SIZE |
                                                   win32con.FILE_NOTIFY_CHANGE_LAST_WRITE |
                                                   win32con.FILE_NOTIFY_CHANGE_SECURITY,
                                                   None,
                                                   None
                                                   )
        changes = []
        for action, file in results:
            full_filename = os.path.join (path_to_watch, file)
            print(full_filename, ACTIONS.get (action, "Unknown"))
            changes.append((action, full_filename))
        
        if func_handle_change:
            # if needed create a thread to handle results
            t = threading.Thread(target=func_handle_change, args = (changes, ))
            t.start()
    

if __name__=='__main__':
    print(__file__, 'test')
    import sys

    if sys.argv[1]:
        DIRECTORY_PATH = sys.argv[1]
    else:
        DIRECTORY_PATH = '.'

imgServer.py

# -*- coding:gbk -*-
# auther : pdm
# email : ppppdm@gmail.com
import os
import sys
import configparser
import threading
import socket

import fileWatcher
import InfoProcess
import dbManager
import readRoadGPS
import mergeManager

DIRECTORY_PATH = ''

def do_process_file(fn):
    infos = do_get_file_infos(fn)
    do_store_db(infos)
    do_merge_file(infos)
    return

def do_get_file_infos(fn):
    infos = InfoProcess.do_get_file_infos(fn)
    return infos

def do_store_db(infos):
    dbManager.store_pic_infos(infos)
    return

def do_merge_file(infos):
    mergeManager.merge_manager(infos)
    return


def handle_change(changes):
    for action, file in changes:
        parent_path = os.path.dirname(os.path.abspath(file))
        if action == 1 and 'jpg' in file and parent_path == DIRECTORY_PATH:
            print(file)
            do_process_file(file)

def readConfig():
    global DIRECTORY_PATH
    
    cf = configparser.ConfigParser()
    cf.read('config.ini')
    cf.sections()
    
    
    dbManager.DB_HOST              = cf.get('db', 'DB_HOST')
    dbManager.USER                 = cf.get('db', 'USER')
    dbManager.PWD                  = cf.get('db', 'PWD')
    dbManager.DATABASE             = cf.get('db', 'DATABASE')
    DIRECTORY_PATH                 = cf.get('parameter', 'DIRECTORY_PATH')
    InfoProcess.MOVE_FILE          = cf.getboolean('rename', 'MOVE_FILE')
    InfoProcess.RENAME_BY_EQUIP    = cf.getboolean('rename', 'RENAME_BY_EQUIP')
    InfoProcess.MOVE_FLODER        = cf.get('rename', 'MOVE_FLODER')
    InfoProcess.CAMERA_EQUIP_FILE  = cf.get('rename', 'CAMERA_EQUIP_FILE')
    InfoProcess.RENAME_BY_DATE     = cf.get('rename', 'RENAME_BY_DATE')
    InfoProcess.USING_IMG_COMPLETE = cf.getboolean('parameter', 'USING_IMG_COMPLETE')
    InfoProcess.TIME_WAIT_FOR_FTP  = cf.getint('parameter', 'TIME_WAIT_FOR_FTP')
    InfoProcess.COFFEE             = cf.getfloat('parameter', 'COFFEE')
    readRoadGPS.ROAD_GPS_FILE      = cf.get('parameter', 'ROAD_GPS_FILE')
    readRoadGPS.ROAD_ARC_FILE      = cf.get('parameter', 'ROAD_ARC_FILE')
    readRoadGPS.DATA_FROM_DB       = cf.getboolean('parameter', 'DATA_FROM_DB')
    mergeManager.DO_MERGE          = cf.getboolean('merge', 'DO_MERGE')
    mergeManager.GROUP_PIC_NUM     = cf.getint('merge', 'GROUP_PIC_NUM')
    mergeManager.MERGE_PICS_PATH   = cf.get('merge', 'MERGE_PICS_PATH')
    
    # Standardization the user input
    DIRECTORY_PATH = os.path.abspath(DIRECTORY_PATH)
    InfoProcess.MOVE_FLODER = os.path.abspath(InfoProcess.MOVE_FLODER) + os.path.sep
    
    
    # print configration
    print('watch floder :', DIRECTORY_PATH)
    print('is rename    :', InfoProcess.MOVE_FILE)
    print('rename floder:', InfoProcess.MOVE_FLODER)
    print('time wait for ftp:', InfoProcess.TIME_WAIT_FOR_FTP)
    print('do merge pic :', mergeManager.DO_MERGE)
    print('merge pic path:', mergeManager.MERGE_PICS_PATH)

def read_camera_equipment():
    if InfoProcess.RENAME_BY_EQUIP and InfoProcess.CAMERA_EQUIP_FILE != '':
        f = open(InfoProcess.CAMERA_EQUIP_FILE, 'rt')
        while True:
            ss = f.readline()
            ss = ss.strip('\n')
            if ss == '':
                break
            arr = ss.split(',')
            InfoProcess.CAMERAID_EQUIPMENTID[arr[0]] = arr[1]
        f.close()
    #print(InfoProcess.CAMERAID_EQUIPMENTID)

def program_is_running():
    try:
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sock.bind(('localhost', 4045))
    except Exception as e:
        print('program bind port 4045 error')
        print(e)
        return True
    
    return False

def main_server():
    
    # should make sure that just one imgServer run on one machine
    if program_is_running():
        print('Program is running')
        return
    
    # init global variables from file config.ini 
    readConfig()
    
    # init roadgps
    readRoadGPS.initRoadInfo()
    
    # start road info demon
    t = threading.Thread(target=readRoadGPS.roadInfoDaemon)
    t.start()
    
    # init camera_equipment_table
    read_camera_equipment()
    
    fileWatcher.watchFileChange(DIRECTORY_PATH, handle_change)
    return

if __name__=='__main__':
    print('imgInfoGeter imgServer start')
    
    if len(sys.argv) > 1:
        DIRECTORY_PATH = sys.argv[1]
    else:
        DIRECTORY_PATH = '.'
    main_server()
    
    ''' # test do process
    fl = ['../res/5.3/20130503170514-db98-0002-1.jpg', 
          '../res/5.3/20130503170514-db98-0002-2.jpg', 
          '../res/5.3/20130503170515-db98-0002-3.jpg']
    for i in fl:
        print(i)
        print(do_process_file(i))
    '''

InfoProcess.py

# -*- coding:gbk -*-
# auther : pdm
# email : ppppdm@gmail.com
import logging
import logging.config
import datetime
import os
import time

import readRoadGPS


#create logger
logging.config.fileConfig("logging.conf")
logger = logging.getLogger("example")


# Global variabls
MOVE_FILE = False
RENAME_BY_EQUIP = False
CAMERAID_EQUIPMENTID = dict()
CAMERA_EQUIP_FILE = ''
MOVE_FLODER = os.path.abspath('../PICS/')+os.path.sep
RENAME_BY_DATE = None

USING_IMG_COMPLETE = False
MODIFY_LAST_BYTE_RTC = False


BEFORE_INFO_LEN = 6
INFO_LEN        = 89
TOTAL_MARK_LEN  = 124
TIME_WAIT_FOR_FTP = 60
COFFEE = 0.0001

INFO_ITMES = ['MAC', 'RTC', 'X', 'Y', 'SPEED', 
              'DIRECT', 'CAR LICENSE', 'LICENSE COLOR', 'CAR DISTENCE', 'SERIAL NUMBER', 
              'NO.', 'CAPTURE FALG', 'CAR LICENSE LEFT POS', 'CAR LICENSE TOP POS'
              ]

INFO_ITEM_LEN = [12, 17, 10, 11, 5, 
                 2, 16, 8, 2, 4, 
                 1, 1, 4, 4
                 ]

MAX_WAIT_OPEN_TIME = 600 # second
EACH_WAIT_OPEN_TIME = 20

ROAD_TIME_TYPE_Tidal = '8a9481d03f79b7d6013f7a0948310003'
ROAD_TIME_TYPE_Daytime = '8a9481d03f79b7d6013f7a0948310002'

# read file and get info in the image
# before the info we want there is 6 bytes file head
# after that is the info we want, the item of info see
# the INFO_ITMES, each item's len see the INFO_ITEM_LEN

def changeToFormate(data):
    data = data[0:2] + b'-' + data[2:4] + b'-' + data[4:6] + b'-' + data[6:8] + b'-' + data[8:10] + b'-' + data[10:12]
    return data

def get_infos(f):
    infos = {}
    
    # in test print the info
    f.seek(BEFORE_INFO_LEN)
    b_data = f.read(INFO_LEN)
    logger.debug(b_data)
    #
    
    
    f.seek(BEFORE_INFO_LEN)
    
    for i in INFO_ITMES:
        item_len = INFO_ITEM_LEN[INFO_ITMES.index(i)]
        b_data = f.read(item_len)
        try:
            if i == 'CAR LICENSE':
                b_data = b_data[:8]
            if i == 'LICENSE COLOR':
                b_data = b_data[:2]
            if i == 'X' or i == 'Y':
                b_data = b_data[:-1]
            if i == 'MAC':
                b_data = changeToFormate(b_data)
            #infos.append((i, str(b_data, 'gbk')))
            infos[i] = str(b_data, 'gbk')
        except:
            #print('decode item %s error!'%(i), b_data)
            logger.debug('decode item %s error! %s'%(i, str(b_data)))
            
    #print(infos)
    return infos

def do_open_file(fn):
    while True:
        # check the file content's length, if not have the infomation ,close and wait
        if os.path.getsize(fn) < BEFORE_INFO_LEN + INFO_LEN:
            time.sleep(EACH_WAIT_OPEN_TIME)
            continue
        try:
            f = open(fn, 'rb')
            break;
        except:
            time.sleep(EACH_WAIT_OPEN_TIME)
    return f

def get_file_time(fn):
    file_st = os.stat(fn)
    return datetime.datetime.fromtimestamp(file_st.st_mtime), datetime.datetime.fromtimestamp(file_st.st_ctime)

def isImageComplete(f):
    # if not use this function always return True
    if USING_IMG_COMPLETE == False:
        return True
    
    # the image file formate is JPEG
    # find the sign of end of image (0xFF 0xD9), if found return true
    ret = False
    f.seek(0)
    
    buff = f.read()
    #print('now len is ', f.tell())
    if b'\xff\xd9' in buff:
        ret = True
    f.seek(0)
    return ret

def get_sub_path_by_date(flag):
    if flag.upper() == 'D':
        return datetime.date.today().isoformat()
    elif flag.upper() == 'M':
        return datetime.date.today().strftime('%Y-%m')
    else:
        return ''

def rename_file(fn, infos):
    print('Is move file', MOVE_FILE)
    if MOVE_FILE:
        if RENAME_BY_EQUIP:
            camera_id = infos['MAC'].upper()
            print(camera_id)
            # There should change to equipment_id with camera_id
            equipment_id = CAMERAID_EQUIPMENTID.get(camera_id, '000000000000')
        
        
            date = infos['DATE'].strftime('%y%m%d%H%M%S')
            number = infos['NO.']
            new_fn = MOVE_FLODER + equipment_id + '-' + date + '-0-000000000000-00000-000-3-' + number + '.jpg'
        elif RENAME_BY_DATE:
            sub_path = get_sub_path_by_date(RENAME_BY_DATE)
            rename_floder = os.path.join(MOVE_FLODER, sub_path)
            if os.path.exists(rename_floder) == False:
                os.mkdir(rename_floder)
            new_fn = os.path.join(rename_floder, os.path.basename(fn))
        else:
            new_fn = MOVE_FLODER + os.path.basename(fn)
        
        old_fn = os.path.abspath(fn)
        # new file should in another directory, else will find the new file created
        while True:
            try:
                os.rename(old_fn, new_fn)
                break
            except:
                # wait for the file
                time.sleep(10)
    
        return new_fn
    else:
        return fn

def get_road_id_from_location(location):
    road_id = ''
    try:
        # the location format is ddmm.mmmm dddmm.mmmm
        x = float(location[0])
        y = float(location[1])
    except:
        logger.error('camera location value error! x:%s y:%s'%(location[0][:-1], location[1][:-1]))
        x, y = 0, 0
    
    # the unit of COFFEE is degree, the minute of mCOFFEE = 60*COFFEE
    mCOFFEE = 60*COFFEE
    
    for p in readRoadGPS.ROAD_GPS_POINT_LIST:
        try:
            rX = float(p[0])
            rY = float(p[1])
        except:
            logger.error('road gps value error! rX:%s rY:%s'%(p[0], p[1]))
            rX , rY = 0, 0
        try:
            rID = p[2]
        except:
            logger.error('road gps have no name')
            rID = ''
        if rX - mCOFFEE < x and x < rX + mCOFFEE and rY - mCOFFEE < y and y < rY + mCOFFEE:
            road_id = rID
            return road_id
    
    return road_id

def get_road_arcinfo_by_id(road_id):
    if road_id == '':
        return None
    
    arc_info = None
    for i in readRoadGPS.ROAD_ARC_INFO_LIST:
        if road_id == i[0]:
            arc_info = i
    return arc_info

def get_forbidding_time(infos):
    road_time_type = infos['ROAD TIME_TYPE']
    if road_time_type == ROAD_TIME_TYPE_Tidal:
        limit_stime = infos['ROAD sTIME']
        limit_etime = infos['ROAD eTIME']
        return limit_stime + ' ' + limit_etime
    if road_time_type == ROAD_TIME_TYPE_Daytime:
        return infos['ROAD TIME']
    return

def do_get_file_infos(fn):
    
    # open the file
    f = do_open_file(fn)
    
    # Determine the integrity of the image file
    # As the image file has not upload completed when open and read it ,
    # we should sleep and wait for the file upload complete.
    
    # sleep 120 second 
    time.sleep(TIME_WAIT_FOR_FTP)
    
    isCmp = isImageComplete(f)
    print(isCmp)
    if isCmp != True:
        logger.error('Error file Img Not Complete:%s', fn)
        f.close()
        return None
    
    infos = get_infos(f)
    
    # close the file after get the info inside 
    f.close()
    
    # get the file create_time and last_modify_time
    m_time, c_time = get_file_time(fn)
    infos['MODIFY TIME'] = m_time
    infos['CREATE TIME'] = c_time
    
    # modify the RTC last byte
    if MODIFY_LAST_BYTE_RTC:
        rtc = infos.get('RTC', '')
        if rtc != '' and rtc[-1] > '9':
            infos['RTC'] = rtc[:-1] + '9'
    
    # get the date
    pic_date = infos.get('RTC', '')
    if pic_date == '':
        pic_date = datetime.datetime.now().date() 
    else:
        #print(pic_date)
        try:
            pic_date = datetime.datetime.strptime(pic_date, '%Y%m%d%H%M%S%f').date()
        except:
            pic_date = datetime.datetime.now().date()
    
    infos['DATE'] = pic_date
    #infos['FILE'] = os.path.basename(fn)
    
    # rename the pic file
    new_fn = rename_file(fn, infos)
    infos['FILE'] = os.path.basename(new_fn)
    infos['FILE PATH'] = os.path.dirname(new_fn)
    infos['FILE SUB PATH'] = os.path.relpath(infos['FILE PATH'], MOVE_FLODER)
    
    # get the road ID info if is in lanes
    try:
        location = (infos['X'], infos['Y'])
    except:
        location = (0.0, 0.0)
    road_id = get_road_id_from_location(location)
    infos['ROAD_ID'] = road_id
    
    # get road arcinfo by road ID
    arcinfo = get_road_arcinfo_by_id(road_id)
    if arcinfo:
        infos['ROAD STATUS'] = arcinfo[1]
        infos['ROAD'] = arcinfo[2]
        infos['ROAD TIME_TYPE'] = arcinfo[3]
        infos['ROAD TIME'] = arcinfo[4]
        infos['ROAD sTIME'] = arcinfo[5]
        infos['ROAD eTIME'] = arcinfo[6]
        infos['FORBIDDING TIME'] = get_forbidding_time(infos)
        
    
    return infos

if __name__=='__main__':
    print(__file__, 'test')
    
    t = 0
    for i in INFO_ITEM_LEN:
        t += i
    print(t)

    
    fl = ['../res/5.3/20130503170514-db98-0002-1.jpg', 
          '../res/5.3/20130503170514-db98-0002-2.jpg', 
          '../res/5.3/20130503170516-db98-0003-1.jpg']
    for i in fl:
        print(i)
        print(do_get_file_infos(i))


mergeManager.py

# -*- coding:gbk -*-
# auther : pdm
# email : ppppdm@gmail.com
import os
import datetime
import mergePics


DO_MERGE = False
GROUP_PIC_NUM = 3
MERGE_PICS_PATH = '../合成图片/'

group_infos = dict()

TIME_DELTA = datetime.timedelta(0, 0, 0, 0, 1)

# store infos in group_infos, 
# return True if have a group info, so can merge pics
# else return False
def have_a_group_info(infos, camera_id, serial_num, collect_time, num):
    infos_list = list()
    _serial_num = 0
    _collect_time = datetime.datetime.now()
    g_infos = group_infos.get(camera_id)
    if g_infos != None:
        infos_list = g_infos[0]
        _serial_num = g_infos[1]
        _collect_time = g_infos[2]
    
    print(_serial_num, _collect_time)
    if g_infos == None:
        infos_list = [infos]
        group_infos[camera_id] = (infos_list, serial_num, collect_time)
        print('merge group info none')
        return False
    elif _serial_num != serial_num:
        infos_list.clear()
        infos_list.append(infos)
        group_infos[camera_id] = (infos_list, serial_num, collect_time)
        print('merge num not equal')
        return False
    elif collect_time - _collect_time > TIME_DELTA:
        infos_list.clear()
        infos_list.append(infos)
        group_infos[camera_id] = (infos_list, serial_num, collect_time)
        print('merge collect time > time delta')
        return False
    else:
        infos_list.append(infos)
        group_infos[camera_id] = (infos_list, serial_num, collect_time)
        if num == GROUP_PIC_NUM and len(infos_list) == GROUP_PIC_NUM:
            return True
        else:
            print('num,len(infos_list)', num, len(infos_list))
            return False

def get_infos(camera_id):
    try:
        return group_infos[camera_id][0]
    except:
        print('have not ', camera_id)
    return

def remove_infos(camera_id):
    try:
        del group_infos[camera_id]
    except:
        print('have not ', camera_id)
    return

def merge_manager(infos):
    if DO_MERGE:
        camera_id = infos.get('MAC', '')
        serial_num = infos.get('SERIAL NUMBER', '0')
        collect_time = infos.get('RTC')
        num = int(infos.get('NO.', '0'))
        try:
            collect_time = datetime.datetime.strptime(collect_time, '%Y%m%d%H%M%S%f')
        except:
            collect_time = datetime.datetime.now()
        
        
        if have_a_group_info(infos, camera_id, serial_num, collect_time, num):
            infos_list = get_infos(camera_id)
            if infos_list != None:
                save_path = os.path.abspath(MERGE_PICS_PATH)
                #print(save_path)
                mergePics.merge_group_imgs(infos_list, save_path)
            remove_infos(camera_id)
        else:
            print('merge wait for a group')
    return


if __name__=='__main__':
    DO_MERGE = True
    merge_manager({'MAC':'00', 'NO.':'01'})
    merge_manager({'MAC':'00', 'NO.':'02'})
    merge_manager({'MAC':'00', 'NO.':'03'})

mergePics.py

# -*- coding:utf-8 -*-
# auther : pdm
# email : ppppdm@gmail.com

# In : 3 pics of one group , info str for whole merge imgs , watermark for each imgs, close_up_para
# Out: merged pic
import os
import datetime
try:
    from PIL import Image, ImageDraw, ImageFont
except:
    print('Warning: need module PIL, should init first')
    PIL = None

info_box_scale = 0.08
info_text_scale = 0.8
watermask_scale = 0.08
watermask_color = (255, 128, 0)
info_text_color = (255, 255, 255)
info_text_pos = (0, 0)
watermask_pos = (0, 0)
info_text_font = "simsun.ttc"
watermask_font = "simsun.ttc"

def merge_pic(imgfiles, infos_str, marks, close_up_para):
    
    if PIL == None:
        print('No module PIL')
        return
    
    imgs = list()
    #print(len(imgfiles), len(marks))
    if len(imgfiles) == 0 or len(imgfiles) != len(marks):
        print('parameter error')
        return
    
    # open the img files
    try:
        for i in imgfiles:
            imgs.append(Image.open(i))
    except Exception as e:
        print(e)
        return
        
    # get img infos
    img1 = imgs[0]
    size = img1.size
    mode = img1.mode
    bbox = img1.getbbox()
    info_box_y = int(size[1]*info_box_scale)
    
    # compose the imgs
    new_size = ((len(imgs)+1)*size[0], info_box_y+size[1])
    new_img = Image.new(mode, new_size)
    
    # draw the close-up pic
    close_up_num = close_up_para[0]
    crop_img = imgs[close_up_num]
    x = close_up_para[1][0]
    y = close_up_para[1][1]
    delta_x = int(close_up_para[2] * size[0])
    delta_y = int(close_up_para[2] * size[1])
    close_up_img = crop_img.transform(size, Image.EXTENT, (x-delta_x, y-delta_y, x+delta_x, y+delta_y))
    imgs.append(close_up_img)
    marks.append(marks[close_up_num])
    
    
    # draw the watermask to each imgs
    watermask_pixel_size = int(size[1]*watermask_scale)
    for i in imgs:
        draw = ImageDraw.Draw(i)
        font = ImageFont.truetype(watermask_font, watermask_pixel_size)
        index = imgs.index(i)
        watermask = marks[index]
        draw.text(watermask_pos, watermask, font=font, fill=watermask_color)
    
    count = 0
    for i in imgs:
        new_img.paste(i, (bbox[0]+count*bbox[2], bbox[1]+info_box_y, bbox[2]+count*bbox[2], bbox[3]+info_box_y))
        count+=1
    
    # draw the info str
    info_str_size = int(info_box_y * info_text_scale)
    draw=ImageDraw.Draw(new_img)
    font = ImageFont.truetype(info_text_font, info_str_size)
    draw.text(info_text_pos, infos_str, font=font, fill=info_text_color)
    
    
    # save the new merged pic
    # void
    
    #new_img.show()
    return new_img

info_items = [('设备编号:', 'MAC'), 
              ('违法地点:', 'ROAD'),
              ('方向:', 'DIRECT'), 
              ('违法时间:', 'RTC'), 
              ('禁行时间:', 'FORBIDDING TIME')]

def calculate_delta_x_scale(distance):
    return 0.9 - distance * 0.06

def formate_direction(dir):
    return dir.replace('e', '东').replace('w', '西').replace('s', '南').replace('n', '北')
    

def merge_group_imgs(infos_list, save_path):
    if len(infos_list) != 3:
        print('infos not enough or too much for merge!')
        return
    
    imgfiles = list()
    infostr = ''
    marks = list()
    infos = infos_list[0]
    
    # get the pics file path
    for i in infos_list:
        try:
            print(i['FILE PATH'], i['FILE'])
            f = os.path.join(i['FILE PATH'], i['FILE'])
            imgfiles.append(f)
        except:
            print('merge not found file infos')
    
    # get the watermask info
    for infos in infos_list:
        try:
            watermark = datetime.datetime.strptime(infos['RTC'], '%Y%m%d%H%M%S%f').strftime('%Y-%m-%d %H:%M:%S.%f')[:-3]
            marks.append(watermark)
        except:
            print('merge not found RTC infos')
    
    # set the Illegal Information
    # use the first pic of group
    for i in info_items:
        s = infos.get(i[1], '')
        if s == '':
            print('get '+ i[0] +' item from pic None!')
            return
        elif i[1] == 'RTC':
            s = datetime.datetime.strptime(infos['RTC'], '%Y%m%d%H%M%S%f').strftime('%Y-%m-%d %H:%M:%S.%f')[:-3]
        elif i[1] == 'DIRECT':
            s = formate_direction(s)
        infostr += i[0]+s+' '
    
    # close-up pic parameter
    pic_num = 2
    license_pos = (650, 600)
    delta_x_scale = calculate_delta_x_scale(int(infos['CAR DISTENCE'])) 
    try:
        license_pos = (int(infos['CAR LICENSE LEFT POS']), int(infos[ 'CAR LICENSE TOP POS']))
    except:
        print('merge not found license_pos')
        # return
    
    close_up_para = [pic_num, license_pos, delta_x_scale]
    
    #print(imgfiles)
    #print(marks)
    new_img = merge_pic(imgfiles, infostr, marks, close_up_para)
    
    # save new_img
    if new_img:
        if os.path.exists(save_path) == False:
            os.mkdir(save_path)
        new_img.save(os.path.join(save_path, infos['RTC']+'-'+infos['MAC']+'-'+infos['NO.']+'.jpg'))
    else:
        print('Error! No merge picture!')

    return

if __name__=='__main__':
    print(__file__, 'test')
    imgfiles = ['../res/6.26_hefei/20130626064148-dcd0-0001-1.jpg', '../res/6.26_hefei/20130626064154-dcd0-0001-2.jpg', '../res/6.26_hefei/20130626064154-dcd0-0001-3.jpg']
    infostr = '设备编号:08-00-28-12-dc-10  违法地点:人民中路(无为路-环城南路)  方向:西向东  违法时间:2013-06-28 17:33:49.471  禁行时间:7:00-20:00'
    marks = ['2013-06-28 17:33:49.471', '2013-06-28 17:33:50.233', '2013-06-28 17:33:50.409']
    close_up_para = [2, (650, 600), 0.25]
    new_img = merge_pic(imgfiles, infostr, marks, close_up_para)
    new_img.show()
    
    
    
    

readRoadGPS.py

# -*- coding:gbk -*-
# auther : pdm
# email : ppppdm@gmail.com

import time
import datetime
import dbManager
import threading

DATA_FROM_DB = False
ROAD_GPS_FILE = ''
ROAD_ARC_FILE = ''
ROAD_GPS_POINT_LIST = list()
ROAD_ARC_INFO_LIST = list()

READ_DB_ROAD_INFO_SLEEP_TIME = 3600 # sec

ROAD_GPS_LOCK = threading.Lock()

LAST_UPDATE_TIME = None


def set_list(data_str):
    l = list()
    coor_arr = data_str.split('\n')
    for i in coor_arr:
        point = i.split(',')
        l.append(point)
    return l

def initRoadGPS(filename):
    global ROAD_GPS_POINT_LIST
    try:
        f = open(filename, 'rt')
        
        data = f.read()
        # set ROAD_GPS_POINT_LIST with data
        ROAD_GPS_POINT_LIST = set_list(data)
        
        f.close()
        print('read road gps done')
    except Exception as e:
        print(e)

def initRoadArc(filename):
    global ROAD_ARC_INFO_LIST
    try:
        f = open(filename, 'rt')
        
        data = f.read()
        # set ROAD_GPS_POINT_LIST with data
        ROAD_ARC_INFO_LIST = set_list(data)
        
        f.close()
        print('read road arc info done')
    except Exception as e:
        print(e)

def initRoadGPS_db(cur):
    global ROAD_GPS_POINT_LIST
    # read arcpoints
    cur.execute("select LATITUDE, LONGITUDE, ARC_ID from t_arcpoints")
    ROAD_GPS_POINT_LIST = cur.fetchall()

def initRoadArc_db(cur):
    global ROAD_ARC_INFO_LIST
   # read arcinfo
    cur.execute("select ID,status,Road_Name,backup1,backup2,Limit_stime,Limit_etime from t_arcinfo")
    ROAD_ARC_INFO_LIST = cur.fetchall()

def read_data_from_db():
    global LAST_UPDATE_TIME
    ret = False
    conn = dbManager.get_db_connect()
    if conn:
        cur = conn.cursor()
        initRoadGPS_db(cur)
        initRoadArc_db(cur)
        print('read gps info from db done!')
        
        LAST_UPDATE_TIME = datetime.datetime.now()
        ret = True
    
    dbManager.close_db_connect(conn)
    return ret

def read_data_from_file():
    initRoadGPS(ROAD_GPS_FILE)
    initRoadArc(ROAD_ARC_FILE)
    return

def initRoadInfo():
    print('DATA_FROM_DB', DATA_FROM_DB)
    if DATA_FROM_DB:
        if read_data_from_db() != True:
            read_data_from_file()
    else:
        read_data_from_file()

def get_last_update_db():
    luu = datetime.datetime(1, 1, 1)
    conn = dbManager.get_db_connect()
    if conn:
        cur = conn.cursor()
        sql = "SELECT last_user_update FROM sys.dm_db_index_usage_stats WHERE object_id=object_id('t_arcinfo') and database_id = db_id('CDMTCP')"
        cur.execute(sql)
        rec = cur.fetchone()
        t_arcinfo_luu  = rec[0]
        
        sql = "SELECT last_user_update FROM sys.dm_db_index_usage_stats WHERE object_id=object_id('t_arcpoints') and database_id = db_id('CDMTCP')"
        cur.execute(sql)
        rec = cur.fetchone()
        t_arcpoints_luu = rec[0]
        
        if t_arcinfo_luu > t_arcpoints_luu:
            luu = t_arcinfo_luu
        else:
            luu = t_arcpoints_luu
        
        
        
    dbManager.close_db_connect(conn)
    return luu

def needUpdate():
    global LAST_UPDATE_TIME
    if LAST_UPDATE_TIME == None:
        return True
    luu = get_last_update_db()
    if luu > LAST_UPDATE_TIME:
        LAST_UPDATE_TIME = luu
        return True
    
    return False

def roadInfoDaemon():
    while DATA_FROM_DB:
        time.sleep(READ_DB_ROAD_INFO_SLEEP_TIME)
        # if t_arcpoints or t_arcinfo updated, then update road info
        # use sys.dm_db_index_usage_stats, the system table of SQL Server
        if needUpdate():
            #ROAD_GPS_LOCK.acquire()
            read_data_from_db()
            #ROAD_GPS_LOCK.release()
            print('update roadinfo from db')
        else:
            print('not needed update roadinfo')

if __name__=='__main__':
    initRoadGPS('roadgps_hefei.txt')
    print(ROAD_GPS_POINT_LIST)


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值