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)