Tryag File Manager
Home
||
Turbo Force
||
B-F Config_Cpanel
Current Path :
/
paip
/
script
/
distribution_abnormal
/
Or
Select Your Path :
Upload File :
New :
File
Dir
//paip/script/distribution_abnormal/img_distribution_abnormal.py
# Copyright (c) 2020~2023 PAIPTREE SmartFarm, Inc. All Rights Reserved. # Author: 조한별 ''' Created on Mon Jan 2 2023 @author: han ''' from datetime import datetime import getopt, sys, cv2, os, warnings, glob from matplotlib import patches, pyplot as plt from matplotlib.ticker import MultipleLocator import numpy as np import pandas as pd from itertools import product from collections import defaultdict from sklearn.mixture import GaussianMixture as GMM warnings.filterwarnings('ignore') HOME_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), os.pardir) MODULE_DIR = 'util' sys.path.append(os.path.join(HOME_PATH, MODULE_DIR)) from PyDBconnector import PyDBconnector from logs import paiplog ## 감지 threshold to alert REGIONTHRESHOLD=.4 SUCCESS_MSG = 'success' FAILED_MSG = 'fail' RESULT_FILE_SUFFIX = '_distributionAbnormalResult' IS_GATEWAY = True ######################################################################################### ## 테스트용 parameter ################################################################## DATA_DIR='../data/형제/' OUTPUT_DIR='../output/형제/' # 이미지 이름 param이 들어오는 경우에는 소스 경로에 아웃풋 이미지가 생성됨 ###################################################################################### ###################### ## hypter parameters # ###################### ############ 가중치 정보. 카메라와의 거리에 따른 가중치 ############### # weightMap = [x/divNum[1] for x in range(1,divNum[1]+1)] ############################################################ ################## mask 정보 : tbl_distribution_abnormal_mask 의 cMapList ########################################## # cMap = defaultdict(lambda : [[0,0],[imgWidth,0],[imgWidth,imgHeight],[0,imgHeight]], eval(cMapStr)) ##################################################################################################### ################## except grid 정보 : tbl_distribution_abnormal_mask 의 exceptList, default value 는 동일 테이블의 defaultExceptList ################## # exceptMap = defaultdict(lambda : eval(mapList.iloc[0,2]), eval(mapList.iloc[0,1])) #################################################################################################################################### #################################################################################################################################### # REGIONTHRESHOLD=.4 #################################################################################################################################### def createFolder(directory): try: if not os.path.exists(directory): os.makedirs(directory) except OSError: print ('Error: Creating directory. ' + directory) def load_image(imgName) : img = cv2.imread(imgName) if img is None : raise Exception('image is not loaded') img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY) return img, gray def applyMask(img_id : str, img, isGray :bool = True) : img_cMap = np.array(cMap[img_id]) mask = np.zeros(img.shape[:2], np.uint8) # maskVal = 255 if isGray else (255, 255, 255) if len(img_cMap) <= 3 : _ = cv2.drawContours(mask, [*img_cMap], -1, (255, 255, 255), -1, cv2.LINE_AA) else : _ = cv2.drawContours(mask, [img_cMap], -1, (255, 255, 255), -1, cv2.LINE_AA) dst = cv2.bitwise_and(img, img, mask=mask) return dst, np.sum(np.where(mask > 0 , 1, 0)), mask @paiplog def getclusteredImage(imgDir, isPlot=False, isDir=True) : weightMap = [x/divNum[1]/2+ .5 for x in range(1,divNum[1]+1)] if isDir : images = glob.glob(imgDir) dirName = OUTPUT_DIR else : images = [imgDir] dirName = os.path.dirname(imgDir) results_df = pd.DataFrame(columns=['fileName','file_time','numOfInterest','interestRatio']) for idx, imgName in enumerate(images) : if IS_GATEWAY : #imgName : /gate/data/filesImageReal/20231108/H02_CT03,1_20231108122102_farm_image_real_2295ae414e7f.jpg img_id = imgName.split('_')[1] dateStr = imgName.split('_')[2] else : #imgName : /paip/data/filesImageReal/FA0001/20231108/FA0001_GW00_H02_CT03,1_20231108122102_farm_image_real_2295ae414e7f.jpg img_id = imgName.split('_')[3] dateStr = imgName.split('_')[4] img = cv2.imread(imgName) img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) img, sumMask, mask = applyMask(img_id, img, isGray=False) original_shape = img.shape img2 = img.reshape((-1, 3)) n_clusters = 4 g_model = GMM(n_components=n_clusters, covariance_type='tied', random_state=0).fit(img2) g_model_index = np.argsort(g_model.means_[:,1])[-(n_clusters-2):] predicted = g_model.predict(img2) color_map_0 = {x: 255 if x in g_model_index else 0 for x in np.unique(predicted)} predicted_color_0 = np.array([color_map_0.get(x) for x in predicted]) result_image_0 = predicted_color_0.reshape(tuple(original_shape[:2])) sumRatio = [] # plot if isPlot : _, ax = plt.subplots(figsize=(30,15)) _ = ax.imshow(result_image_0) ax.xaxis.set_major_locator(MultipleLocator(grid_xsize)) ax.xaxis.set_major_formatter('{x:.0f}') ax.yaxis.set_major_locator(MultipleLocator(grid_ysize)) ax.yaxis.set_major_formatter('{x:.0f}') except_list = exceptMap[img_id] for idx, (x, y) in enumerate(ziped_xy) : mask_sum = np.sum(np.where(mask[y:y+grid_ysize,x:x+grid_xsize] > 0 , 1, 0)) img_sum = np.sum(np.where(mask[y:y+grid_ysize,x:x+grid_xsize] > 0 , 1, 0) & np.where(result_image_0[y:y+grid_ysize,x:x+grid_xsize] > 0, 1, 0)) ratioRegion = np.round(img_sum/mask_sum,1) if mask_sum > 0 else 0. sumRatio.append(np.round(weightMap[int(idx%divNum[1])] * ratioRegion,2)) if idx not in except_list : if ratioRegion <= regionThreshold : rect=patches.Rectangle((x,y),grid_xsize,grid_ysize, #fill=False, alpha=0.5, facecolor="red") ax.add_patch(rect) _ = plt.text(x, y+35, f'{idx}:{ratioRegion}', color='red', size=20, weight='bold') else : _ = plt.text(x, y+35, f'{idx}:{ratioRegion}', color='green', size=20, weight='bold') else : _ = plt.text(x, y+35, f'{idx}:{ratioRegion}', color='green', size=20, weight='bold') _ = plt.grid() plt.tight_layout() createFolder(dirName) plt.savefig(f"{dirName}/{os.path.splitext(os.path.basename(imgName))[0]}{RESULT_FILE_SUFFIX}.jpg") # plt.show() else : for idx, (x, y) in enumerate(ziped_xy) : mask_sum = np.sum(np.where(mask[y:y+grid_ysize,x:x+grid_xsize] > 0 , 1, 0)) img_sum = np.sum(np.where(mask[y:y+grid_ysize,x:x+grid_xsize] > 0 , 1, 0) & np.where(result_image_0[y:y+grid_ysize,x:x+grid_xsize] > 0, 1, 0)) ratioRegion = np.round(img_sum/mask_sum,1) if mask_sum > 0 else 0. sumRatio.append(np.round(weightMap[int(idx%divNum[1])] * ratioRegion,2)) results_df.loc[len(results_df)] = [imgName, dateStr, sumMask, sumRatio] return results_df def getDBData(dbConn, sql_str) : try : return dbConn.select_from_db(sql_str) except : return None @paiplog def insertDatabase(dbConn, data_df, isInsert=True) : try: create_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S") if isInsert : # insert new InDate for pdRow in data_df.iterrows(): aFileName = os.path.splitext(pdRow[1]['org_file_name']) # print(aFileName[0]+RESULT_FILE_SUFFIX+aFileName[1]) if IS_GATEWAY : insert_string = f'''insert into tbl_image_analysis_distribution_abnormal (create_time, house_id, module_id, data_type, file_time, org_file_name, result_file_name, cluster_num_of_interest, cluster_interest_ratio_list, cluster_abnormal_prediction_status) values('{create_time}', '{pdRow[1]['house_id']}', '{pdRow[1]['module_id']}', 'real', '{pdRow[1]['file_time']}', '{pdRow[1]['org_file_name']}', '{aFileName[0]+RESULT_FILE_SUFFIX+aFileName[1]}', {pdRow[1]['numOfInterest']}, '{pdRow[1]['interestRatio']}', 'success');''' else : insert_string = f'''insert into tbl_farm_image_analysis_distribution_abnormal (create_time, farm_id, gateway_id, house_id, module_id, data_type, file_time, org_file_name, result_file_name, cluster_num_of_interest, cluster_interest_ratio_list, cluster_abnormal_prediction_status) values('{create_time}', '{pdRow[1]['farm_id']}', '{pdRow[1]['gateway_id']}', '{pdRow[1]['house_id']}', '{pdRow[1]['module_id']}', 'real', '{pdRow[1]['file_time']}', '{pdRow[1]['org_file_name']}', '{aFileName[0]+RESULT_FILE_SUFFIX+aFileName[1]}', {pdRow[1]['numOfInterest']}, '{pdRow[1]['interestRatio']}', 'success');''' dbConn.insert_to_db(insert_string) return True else : # update to modify OutDate pass except Exception as e: raise Exception('insert query error!') @paiplog def main(argv): PYTHON_FILE_NAME = argv[0] imgHeight, imgWidth = 1080, 1920 divNum = [12,8] grid_xsize, grid_ysize = int(imgWidth / divNum[0]), int(imgHeight / divNum[1]) # print(f"grid size : {grid_xsize, grid_ysize}") grid_x_all = [x for x in range(0,imgWidth,int(grid_xsize))] grid_y_all = [x for x in range(0,imgHeight,int(grid_ysize))] ziped_xy = list(product(grid_x_all, grid_y_all)) regionThreshold = REGIONTHRESHOLD FileName=None try: # opts: getopt 옵션에 따라 파싱 ex) [('-i', 'myinstancce1')] # etc_args: getopt 옵션 이외에 입력된 일반 Argument # argv 첫번째(index:0)는 파일명, 두번째(index:1)부터 Arguments opts, etc_args = getopt.getopt(argv[1:], \ "h:i:w:d:t:f:", ["help","imgHeight=","imgWidth=","divNum=","regionThreshold=",'FileName=']) except getopt.GetoptError: # 옵션지정이 올바르지 않은 경우 print(PYTHON_FILE_NAME, '-ih <imgHeight> -iw <imgWidth> -d <divNum> -t <regionThreshold>') sys.exit(2) for opt, arg in opts: # 옵션이 파싱된 경우 if opt in ("-h", "--help"): # HELP 요청인 경우 사용법 출력 print(PYTHON_FILE_NAME, '-ih <imgHeight> -iw <imgWidth> -d <divNum>::[width_num, height_num] -t <regionThreshold> -f <FileName>') sys.exit() elif opt in ("-i", "--imgHeight"): imgHeight = int(arg) elif opt in ("-w", "--imgWidth"): imgWidth = int(arg) elif opt in ("-d", "--divNum"): divNum = eval(arg) elif opt in ("-t", "--regionThreshold"): regionThreshold = float(arg) elif opt in ("-f", "--FileName"): FileName = arg return (imgHeight, imgWidth, divNum, grid_xsize, grid_ysize, grid_x_all, grid_y_all, ziped_xy, regionThreshold, FileName) if __name__ == '__main__' : try : imgHeight, imgWidth, divNum, grid_xsize, grid_ysize, grid_x_all, grid_y_all, ziped_xy, regionThreshold, FileName = main(sys.argv) if FileName is None: raise Exception('Not Exist FileName!!') if os.path.basename(FileName).startswith('FA'): IS_GATEWAY = False dbConn = PyDBconnector() if IS_GATEWAY : sqlStr = f'''select cMapList, exceptList, defaultExceptList from tbl_distribution_abnormal_mask order by create_time desc limit 1''' else : farmID = os.path.basename(FileName).split('_')[0] sqlStr = f'''select cMapList, exceptList, defaultExceptList from tbl_farm_distribution_abnormal_mask where farmID = '{farmID}' order by create_time desc limit 1''' # from DB mapList = getDBData(dbConn,sqlStr) # threshold cMapStr = str(mapList.iloc[0,0]).replace('array','np.array') cMap = defaultdict(lambda : [[0,0],[imgWidth,0],[imgWidth,imgHeight],[0,imgHeight]], eval(cMapStr)) exceptMap = defaultdict(lambda : eval(mapList.iloc[0,2]), eval(mapList.iloc[0,1])) # threshold test code ## 어울 농장 #################################################################################################################################################################################################################################### # cMap = defaultdict(lambda : [[0,0],[imgWidth,0],[imgWidth,imgHeight],[0,imgHeight]]) # exceptMap = defaultdict(lambda : eval(mapList.iloc[0,2])) # cMap['CT01,4'] = np.array([[0,650],[530,305],[530,443],[610,443],[610,249],[645,230],[735,230],[735,277],[784,277],[784,230],[1040,230],[1040,325],[1097,325],[1097,222],[1215,222],[1920,775],[1920,1080],[0,1080]]) # cMap['CT04,4'] = np.array([[0,770],[666,208],[764,208],[764,360],[823,360],[823,208],[1085,208],[1085,265],[1125,265],[1125,208],[1225,208],[1264,230],[1264,505],[1332,505],[1340,277],[1920,665],[1920,1080],[0,1080]]) # cMap['CT01,2'] = np.array([[0,630],[549,176],[598,176],[615,692],[744,692],[744,176],[1270,194],[1270,340],[1342,340],[1342,200],[1445,200],[1920,550],[1920,1080],[0,1080]]) # cMap['CT04,2'] = np.array([[0,582],[470,290],[507,290],[509,508],[588,508],[588,277],[1176,277],[1156,803],[1293,803],[1312,287],[1351,297],[1920,803],[1920,1080],[0,1080]]) # exceptMap['CT01,3'] = [] # exceptMap['CT04,3'] = [] # exceptMap['CT04,2'] = [0,1,2,3,8,9,10,16,17,24,25,32,33,40,41,48,49,56,57,64,65,72,73,80,81,82,88,89,90,91] # exceptMap['CT01,2'] = [0,1,2,8,9,16,24,32,40,48,56,64,72,80,81,88,89,90] ### exceptMap default : [0,1,2,3,8,9,10,16,17,24,32,40,48,56,64,65,72,73,80,81,82,88,89,90,91] ## 어울 농장 #################################################################################################################################################################################################################################### # cMap = defaultdict(lambda : [[0,0],[imgWidth,0],[imgWidth,imgHeight],[0,imgHeight]]) # exceptMap = defaultdict(lambda : [0,1,2,8,9,16,17,24,32,56,64,72,80,81,88,89,90]) # cMap = {"CT07,2" : np.array([[0,526],[509,111],[1528,138],[1920,415],[1920,1080],[0,1080]]), # "CT07,3" : np.array([[0,0],[1920,0],[1920,1080],[0,1080]]), # "CT07,4" : np.array([[0,554],[823,111],[1920,180],[1920,1080],[0,1080]])} ## 미리 농장 #################################################################################################################################################################################################################################### # setup mask # cMap = defaultdict(lambda : [[0,0],[imgWidth,0],[imgWidth,imgHeight],[0,imgHeight]]) # exceptMap = defaultdict(lambda : [0,1,2,3,8,9,10,16,17,24,32,40,48,56,64,65,72,73,80,81,82,88,89,90,91]) # cMap['CT01,2'] = np.array([[[0,0],[860,0],[430,1080],[0,1080]],[[1200,0],[1920,0],[1920,1080],[1310,1080]]]) # cMap['CT01,4'] = np.array([[[0,471],[353,200],[1019,200],[920,1080],[0,1080]],[[1360,200],[1650,200],[1920,498],[1920,1080],[1670,1080]]]) # cMap['CT04,2'] = np.array([[[0,200],[80,138],[490,138],[83,1080],[0,1080]],[[770,138],[1510,138],[1920,443],[1920,1080],[840,1080]]]) # cMap['CT04,4'] = np.array([[[235,0],[764,0],[740,1080],[0,1080],[0,166]],[[960,0],[1136,0],[1920,858],[1920,1080],[1480,1080]]]) # cMap['CT07,2'] = np.array([[0,332],[370,0],[627,0],[420,560],[901,560],[830,0],[1270,0],[1920,480],[1920,1080],[0,1080]]) # cMap['CT07,4'] = np.array([[0,0],[815,0],[764,526],[1332,526],[1050,0],[1920,0],[1920,1080],[0,1080]]) # exceptMap['CT01,3'] = [] # exceptMap['CT04,3'] = [] # exceptMap['CT07,3'] = [] ## 미리 농장 #################################################################################################################################################################################################################################### # FileName : '/gate/data/filesImageReal/20231109/H01_CT01,5_20231109124011_farm_image_real_d3c76530416a.jpg' # FileName : '/paip/data/filesImageReal/FA0001/20231109/FA0001_GW00_H01_CT01,5_20231109124011_farm_image_real_d3c76530416a.jpg' results_df = getclusteredImage(FileName, isPlot=True, isDir=False) #test code... #results_df = getclusteredImage(DATA_DIR + os.path.sep + '*.jpg', isPlot=True, isDir=True) # create columns results_df['org_file_name'] = [os.path.basename(x) for x in results_df.fileName] results_df['farm_id'] = [x[0] if x[0].startswith('FA') else '' for x in results_df.org_file_name.str.split('_')] results_df['gateway_id'] = [x[1] if x[0].startswith('FA') else '' for x in results_df.org_file_name.str.split('_')] results_df['house_id'] = [x[2] if x[0].startswith('FA') else x[0] for x in results_df.org_file_name.str.split('_')] results_df['module_id'] = [x[3] if x[0].startswith('FA') else x[1] for x in results_df.org_file_name.str.split('_')] if len(results_df) > 0 : insertDatabase(dbConn, results_df, isInsert=True) print(SUCCESS_MSG) except : print(FAILED_MSG)