def preprocess(imgOriginal, PreprocessCvcSel, PreprocessMode, PreprocessGaussKernel, PreprocessThreshBlockSize, PreprocessThreshweight, PreprocessMorphKernel, PreprocessMedianBlurKernel, PreprocessCannyThr): """ CSC, Contrast stretch (morph.), Blurring and Adaptive-Threshold """ # Color-Space-Conversion (CSC): switch from BGR to HSV and take the requested component: imgHSV = cvtColor(imgOriginal, COLOR_BGR2HSV) imgHSV_H, imgHSV_S, imgHSV_V = split(imgHSV) if PreprocessCvcSel == "H": imgGrayscale = imgHSV_H elif PreprocessCvcSel == "S": imgGrayscale = imgHSV_S elif PreprocessCvcSel == "V": imgGrayscale = imgHSV_V else: error("Unsupported PreprocessCvcSel mode: %s" % PreprocessCvcSel) # -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. if PreprocessMode == "Legacy": # Increase Contrast (morphological): imgMaxContrastGrayscale = maximizeContrast(imgGrayscale, PreprocessMorphKernel) # Blurring: imgBlurred = GaussianBlur(imgMaxContrastGrayscale, PreprocessGaussKernel, 0) # Adaptive Threshold: imgThresh = adaptiveThreshold(imgBlurred, 255.0, ADAPTIVE_THRESH_GAUSSIAN_C, THRESH_BINARY_INV, PreprocessThreshBlockSize, PreprocessThreshweight) # -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. elif PreprocessMode == "BlurAndCanny": # Blurring: imgBlurred = medianBlur(imgGrayscale, PreprocessMedianBlurKernel) # Canny Edge Detection: imgThresh = Canny(imgBlurred, PreprocessCannyThr / 2, PreprocessCannyThr) # -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. else: error("Unsupported PreprocessMode mode: %s" % PreprocessMode) imgGrayscale = imgBlurred return imgGrayscale, imgThresh
def endDocument(self): if self.include is not None: for k,v in self.conf.pathCollection.iteritems(): if v['type'] not in 'output': if not os.path.exists(v['path']): error('Path {!s} defined in {!s} does not exist'.format(v['path'], self.include)) # if k in self.project_info.keys(): # error('Path-ID {!s} in {!s} already used in different context. Please, choose \ # a different Path-ID'.format(k,self.include)) # else: # self.project_info[k] = v['path'] os.putenv("ESMValTool_" + k, str(v['path']))
def perspective_alignment(possible_marks_list, perspectiveMode, rotation_angle_deg, debugMode): """ Wrapper function for Perspective Alignment """ if perspectiveMode == 0: return perspective_alignment_opt0(possible_marks_list, rotation_angle_deg, debugMode) elif perspectiveMode == 1: return perspective_alignment_opt1(possible_marks_list, debugMode) else: error("Invalid perspectiveMode (%d)" % perspectiveMode) return [], []
def execute(self, executable, project_info, verbosity, exit_on_warning): try: with open(self.filename, "w") as f: f.write("0") f.close() except IOError: raise error("IOError while open/write: '{0}'".format(filename)) if not os.path.exists(executable): raise IOError("file to execute is missing: {0}".format(executable)) cmd = self.lang + " {0}".format(executable) run_application = subprocess.Popen(cmd, shell=True, stdin=open(os.devnull), stdout=subprocess.PIPE, stderr=subprocess.PIPE) run_application.wait() output = run_application.communicate() std_out = filter(None, output[0].split('\n')) std_err = filter(None, output[1].split('\n')) for i in [self.lang.upper() + ' INFO : ' + item for item in std_out]: print i for i in [self.lang.upper() + ' ERROR: ' + item for item in std_err]: print i for key in [ env for env in os.environ if re.search('^ESMValTool_*', env) ]: del (os.environ[key])
def get_monthly_input(project_info, mn, time, lon, lat, time_bnds_1, pr, sm, fileout, samplefileout, model, verbosity): """ ;; Arguments ;; mn: int ;; month, values from 1 to 12 ;; time: iris cube coords ;; time info of cube ;; lon: array [lon] ;; longitude ;; lat: array [lat] ;; latitude ;; time_bnds_1: float ;; first time_bnd of time series ;; pr: iris cube [time, lat, lon] ;; 3-hourly precipitation time series ;; sm: iris cube [time, lat, lon] ;; 3-hourly soil moisture time series ;; fileout: dir ;; output directory ;; samplefileout: dir ;; temporary outpout directory used by fortran routines ;; ;; Return ;; prbef: array [year, day time steps (=8), lat, lon] ;; 3-hourly precipitation in the previous day ;; smbef: array [year, day time steps (=8), lat, lon] ;; 3-hourly soil moisture in the previous day ;; praf: array [year, day time steps (=8), lat, lon] ;; 3-hourly precipitation in the following day ;; smaft: array [year, day time steps (=8), lat, lon] ;; 3-hourly soil moisture in the following day ;; monthlypr: array [year, days in month * day time steps, lat, lon] ;; 3-hourly precipitation in month mn for the whole analysis period ;; monthlysm: array [year, days in month * day time steps, lat, lon] ;; 3-hourly soil moisture in month mn for the whole analysis period ;; days_per_year: int ;; number of days per year ;; ;; Description ;; Prepare monthly input data for fortran routines ;; """ import projects E = ESMValProject(project_info) verbosity = E.get_verbosity() #------------------------- # Read model info #------------------------- model = project_info['MODELS'][0] currProject = getattr(vars()['projects'], model.split_entries()[0])() model_info = model.split_entries() # -------------------------------------- # Get grid and calendar info # -------------------------------------- utimedate = time[0].units first_year = int(model_info[5]) last_year = int(model_info[6]) nyr = last_year - first_year + 1 years = np.arange(nyr) + first_year months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'] calendar = utimedate.calendar nx = len(lon) ny = len(lat) days_permonth_360 = [30 for i in range(0, 12)] days_permonth_noleap = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] days_permonth_leap = [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] if calendar == '360_day': days_per_year = 360 days_permonth = days_permonth_360 nts = [8 * dpm for dpm in days_permonth_360] elif any([calendar == '365_day', calendar == 'noleap']): days_per_year = 365 days_permonth = days_permonth_noleap nts = [8 * dpm for dpm in days_permonth_noleap] elif any([calendar == 'gregorian', calendar == 'standard']): days_per_year = 365 days_permonth = days_permonth_noleap nts = [8 * dpm for dpm in days_permonth_noleap] # Leap days are considered by get_monthly_input() else: error('Missing calendar info') # -------------------------------------- # Create pr, sm before and after arrays # -------------------------------------- prbef = np.zeros((nyr, 8, ny, nx), dtype='f4') praft = np.zeros((nyr, 8, ny, nx), dtype='f4') smbef = np.zeros((nyr, 8, ny, nx), dtype='f4') smaft = np.zeros((nyr, 8, ny, nx), dtype='f4') try: os.mkdir(os.path.join(samplefileout, "5x5G_mon" + str(mn).zfill(2)), stat.S_IWUSR | stat.S_IRUSR | stat.S_IXUSR | stat.S_IRGRP | stat.S_IXGRP | stat.S_IROTH | stat.S_IXOTH) except OSError as exc: if exc.errno != errno.EEXIST: raise exc pass try: os.mkdir(os.path.join(fileout, "event_output", "mon" + str(mn).zfill(2)), stat.S_IWUSR | stat.S_IRUSR | stat.S_IXUSR | stat.S_IRGRP | stat.S_IXGRP | stat.S_IROTH | stat.S_IXOTH) except OSError as exc: if exc.errno != errno.EEXIST: raise exc pass nt = nts[mn - 1] monthlypr_list = [np.zeros((nt, ny, nx), dtype='f4') for y in years] monthlysm_list = [np.zeros((nt, ny, nx), dtype='f4') for y in years] for yr, year in enumerate(years): info('month, year: ' + str(mn) + ", " + str(year), verbosity, required_verbosity=1) if all([mn == 2, any([calendar == 'gregorian', calendar == 'standard'])]): monthlysm_list[yr][:,:,:] = ( sm.extract(iris.Constraint(month=months[mn-1],year=year, dom = range(1,29) )).data) monthlypr_list[yr][:,:,:] = ( pr.extract(iris.Constraint(month=months[mn-1],year=year, dom = range(1,29) )).data) else: try: monthlypr_list[yr][:,:,:] = ( pr.extract(iris.Constraint(month=months[mn-1],year=year)).data) except: try: monthlypr_list[yr][0,:,:] = -999. monthlypr_list[yr][1::,:,:] = ( pr.extract(iris.Constraint(month=months[mn-1],year=year)).data) except: info('omitted pr: ' + str(mn) + ", " + str(year), verbosity, required_verbosity=1) try: monthlysm_list[yr][:,:,:] = ( sm.extract(iris.Constraint(month=months[mn-1],year=year)).data) except: try: monthlysm_list[yr][0,:,:] = -999. monthlysm_list[yr][1::,:,:] = ( sm.extract(iris.Constraint(month=months[mn-1],year=year)).data) except: info('omitted sm: ' + str(mn) + ", " + str(year), verbosity, required_verbosity=1) # last day of previous month if all([mn == 1, year == first_year]): prbef[yr,:,:,:] = np.zeros( (8, ny, nx) ) - 999. smbef[yr,:,:,:] = np.zeros( (8, ny, nx) ) - 999. elif (mn == 1): prbef[yr,:,:,:] = ( pr.extract(iris.Constraint(year=year-1,month='Dec',dom=days_permonth[-1])).data) smbef[yr,:,:,:] = ( sm.extract(iris.Constraint(year=year-1,month='Dec',dom=days_permonth[-1])).data) else: if any([calendar == '360_day', calendar == '365_day', calendar == 'noleap']): prbef[yr,:,:,:] = ( pr.extract(iris.Constraint(year=year,month=months[mn-2],dom=days_permonth[mn-2])).data) smbef[yr,:,:,:] = ( sm.extract(iris.Constraint(year=year,month=months[mn-2],dom=days_permonth[mn-2])).data) elif any([calendar == 'gregorian', calendar == 'standard']): if cal.isleap(year): prbef[yr,:,:,:] = ( pr.extract(iris.Constraint(year=year,month=months[mn-2],dom=days_permonth_leap[mn-2])).data) smbef[yr,:,:,:] = ( sm.extract(iris.Constraint(year=year,month=months[mn-2],dom=days_permonth_leap[mn-2])).data) else: prbef[yr,:,:,:] = ( pr.extract(iris.Constraint(year=year,month=months[mn-2],dom=days_permonth[mn-2])).data) smbef[yr,:,:,:] = ( sm.extract(iris.Constraint(year=year,month=months[mn-2],dom=days_permonth[mn-2])).data) # first day of following month if (mn == 12 and year == last_year): praft[yr,:,:,:] = np.zeros( (8, ny, nx) ) - 999. smaft[yr,:,:,:] = np.zeros( (8, ny, nx) ) - 999. elif (mn == 12): praft[yr,:,:,:] = ( pr.extract(iris.Constraint(year=year+1,month='Jan',dom=1)).data) smaft[yr,:,:,:] = ( sm.extract(iris.Constraint(year=year+1,month='Jan',dom=1)).data) else: if any([calendar == '360_day', calendar == '365_day', calendar == 'noleap']): praft[yr,:,:,:] = ( pr.extract(iris.Constraint(year=year,month=months[mn],dom=1)).data) smaft[yr,:,:,:] = ( sm.extract(iris.Constraint(year=year,month=months[mn],dom=1)).data) elif any([calendar == 'gregorian', calendar == 'standard']): if all([cal.isleap(year),mn == 2]): praft[yr,:,:,:] = ( pr.extract(iris.Constraint(year=year,month=months[1],dom=29)).data) smaft[yr,:,:,:] = ( sm.extract(iris.Constraint(year=year,month=months[1],dom=29)).data) else: praft[yr,:,:,:] = ( pr.extract(iris.Constraint(year=year,month=months[mn],dom=1)).data) smaft[yr,:,:,:] = ( sm.extract(iris.Constraint(year=year,month=months[mn],dom=1)).data) monthlypr = np.vstack(tuple(monthlypr_list)) monthlysm = np.vstack(tuple(monthlysm_list)) monthlypr = monthlypr.reshape(nyr, nt, ny, nx) monthlysm = monthlysm.reshape(nyr, nt, ny, nx) if time_bnds_1 == 0.0625: monthlypr[:, 0:-1, :, :] = monthlypr[:, 1::, :, :] monthlypr[:, -1, :, :] = -9999. prbef[:, 0:-1, :, :] = prbef[:, 1::, :, :] praft[:, 0:-1, :, :] = praft[:, 1::, :, :] prbef[:, -1, :, :] = -9999. praft[:, -1, :, :] = -9999. return prbef, smbef, praft, smaft, monthlypr, monthlysm, days_per_year
# Get command arguments. input_xml_full_path = args[0] # Parse input namelist into project_info-dictionary. Project = xml_parsers.namelistHandler() parser = xml.sax.make_parser() parser.setContentHandler(Project) parser.parse(input_xml_full_path) # Project_info is a dictionary with all info from the namelist. project_info = Project.project_info if options.reformat: if 'REFORMAT' not in project_info.keys(): error('No REFORMAT tag specified in {0}'.format(input_xml_full_path)) if len(project_info['REFORMAT']) == 0: info('No reformat script specified', 1, 1) print_header({}, options.reformat) for k, v in project_info['REFORMAT'].iteritems(): if not os.path.exists(v): error('Path {0} does not exist'.format(v)) projects.run_executable(v, project_info, 1, False, write_di=False) sys.exit(0) verbosity = project_info['GLOBAL']['verbosity'] climo_dir = project_info['GLOBAL']['climo_dir'] exit_on_warning = project_info['GLOBAL'].get('exit_on_warning', False) # Additional entries to 'project_info'. The 'project_info' construct # is one way by which Python passes on information to the NCL-routines.
def __init__(self, shell): if shell in ['csh', 'bash']: self.lang = shell else: raise error('Unknown shell: {0}'.format(shell)) super(shell_launcher, self).__init__()
def decode_marks(marks_list, MarksRows, MarksCols, frame_shape, rotation_angle_deg, debugMode=False): if len(marks_list) < MarksRows: return # Extract XY min/max for the given marks: X = array([[x.intCenterX_r, x.intCenterY_r] for x in marks_list]) min_x = min(X[:, 0]) max_x = max(X[:, 0]) min_y = min(X[:, 1]) + 5 max_y = max(X[:, 1]) if (max_y > 310): max_y -= 5 # Prepare KNN origins: if 80 < abs(rotation_angle_deg) < 100: # Adaptive scale fix min_x -= 1 max_x += 1 radius_y = (max_y - min_y) / (MarksRows - 1) radius_x = (max_x - min_x) / (MarksCols - 1) y_scale = list(range(min_y, max_y, int(radius_y))) if radius_y > 0 else [1] x_scale = list(range(min_x, max_x, int(radius_x))) if radius_x > 0 else [1] if len(y_scale) < MarksRows: y_scale.append(max_y) if len(x_scale) < MarksCols: x_scale.append(max_x) # For each KNN origin, seek for closest mark: debug("x_scale = " + str(x_scale), debugMode) debug("y_scale = " + str(y_scale), debugMode) code_str = "" for y in y_scale: for x in x_scale: ret = seek_for_mark(x, y, marks_list, int(radius_x), int(radius_y)) code_str += "%s" % ret debug("code before flip: %s" % code_str, debugMode) # Code must start with '1' and end with '0', flip if not: if code_str[0] == '0' and code_str[-1] == '1': code_str = code_str[::-1] debug("code after flip: %s" % code_str, debugMode) elif code_str[0] == code_str[-1]: error("Invalid code detected! (first mark equals to last mark)") code_hex_str = hex(int(code_str, 2)) # -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. # Debug: if debugMode: height, width = frame_shape aligned_frame = zeros((height, width, 3), uint8) for x in x_scale: for y in y_scale: aligned_frame[y - 2:y + 2, x - 2:x + 2, 1] = 255 for mark in marks_list: aligned_frame[mark.intCenterY - 3:mark.intCenterY + 3, mark.intCenterX - 3:mark.intCenterX + 3, 2] = 255 aligned_frame[mark.intCenterY_r - 3:mark.intCenterY_r + 3, mark.intCenterX_r - 3:mark.intCenterX_r + 3, 0] = 255 putText(aligned_frame, "Original", (10, 30), FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2) putText(aligned_frame, "Rotation fix (SVD)", (10, 70), FONT_HERSHEY_SIMPLEX, 1, (255, 0, 0), 2) putText(aligned_frame, "KNN origins", (10, 110), FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2) imwrite("img_possible_marks_aligned.jpg", aligned_frame) return code_hex_str
def add_nml_entry(self, name, string, attributes): if attributes['id'] in self.project_info.keys(): error('Duplicate usage of reformat_script id: {0}'.format( attributes['id'])) self.project_info[attributes['id']] = string.strip()
def perspective_alignment_opt1(possible_marks_list, debugMode): """ Calculate the src2dst homography and apply a Perspective Warp, in order to fix camera lens geometric distortion """ # Option1: | Option2: # | # - ... X2 | X3 ... X1 # . ... . | . ... . # X1 ... X3 | X2 ... - # # 1. Find two largest Xs neighbours (<W/2), which are vertically spaced by at least 2*H --> if found, we're in Option1 # Else --> Find two smallest Xs neighbours (<W/2), which are vertically spaced by at least 2*H --> if found, we're in Option2 # Else --> ERROR # # 2. If we're in Option1 --> X1 = smallest X with largest Y coordinate # P0 (marked with '-'): { X0, Y0 - 4*H } # Else (option2) -------> X1 = largest X with smallest Y coordinate # P0 (marked with '-'): { X0, Y0 + 4*H } # # 3. Calculate Homography (src2dst): {P0,P1,P2,P3} --> rectangle, based on min/max combinations # # 4. Perspective Warp # -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. # Extract marks relevant data: X = [[ x.intCenterX_r, x.intCenterY_r, x.intBoundingRectWidth, x.intBoundingRectHeight ] for x in possible_marks_list] X.sort() X = array(X) # -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. # Option1: if perspective_warp_x23_dist_check(X[-1, :], X[-3, :]): option_num = 1 p2 = X[-1, 0:2] p3 = X[-3, 0:2] if X[-3, 1] < X[-1, 1]: p2 = X[-3, 0:2] p3 = X[-1, 0:2] elif perspective_warp_x23_dist_check(X[-1, :], X[-2, :]): option_num = 1 p2 = X[-1, 0:2] p3 = X[-2, 0:2] if X[-2, 1] < X[-1, 1]: p2 = X[-2, 0:2] p3 = X[-1, 0:2] elif perspective_warp_x23_dist_check(X[-2, :], X[-3, :]): option_num = 1 p2 = X[-2, 0:2] p3 = X[-3, 0:2] if X[-3, 1] < X[-2, 1]: p2 = X[-3, 0:2] p3 = X[-2, 0:2] # -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. # Option2: elif perspective_warp_x23_dist_check(X[0, :], X[2, :]): option_num = 2 p2 = X[0, 0:2] p3 = X[2, 0:2] if X[2, 1] > X[0, 1]: p2 = X[2, 0:2] p3 = X[0, 0:2] elif perspective_warp_x23_dist_check(X[0, :], X[1, :]): option_num = 2 p2 = X[0, 0:2] p3 = X[1, 0:2] if X[1, 1] > X[0, 1]: p2 = X[1, 0:2] p3 = X[0, 0:2] elif perspective_warp_x23_dist_check(X[1, :], X[2, :]): option_num = 2 p2 = X[1, 0:2] p3 = X[2, 0:2] if X[2, 1] > X[1, 1]: p2 = X[2, 0:2] p3 = X[1, 0:2] # -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. # Error (unexpected state): else: error("Unexpected perspective option! (neither 1 or 2)") return # -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. # P1: if option_num == 1: p0 = array([X[0, 0], X[0, 1] - 4 * X[0, 3]]) p1 = X[0, 0:2] if (abs(X[0, 0] - X[1, 0]) < mean([X[0, 2], X[1, 2]]) / 1.5) and X[1, 1] > X[0, 1]: p0 = array([X[1, 0], X[1, 1] - X[1, 3]]) p1 = X[1, 0:2] else: p0 = array([X[-1, 0], X[-1, 1] + 4 * X[-1, 3]]) p1 = X[-1, 0:2] if (abs(X[-1, 0] - X[-2, 0]) < mean([X[-1, 2], X[-2, 2]]) / 1.5) and X[-2, 1] < X[-1, 1]: p0 = array([X[-2, 0], X[0, 1] + X[-2, 3]]) p1 = X[-2, 0:2] # -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. # Source rectangle: if option_num == 1: rect_src = [list(p0), list(p1), list(p3), list(p2)] else: rect_src = [list(p3), list(p2), list(p0), list(p1)] # Destination rectangle: min_x = min(X[:, 0]) max_x = max(X[:, 0]) min_y = min(X[:, 1]) max_y = max(X[:, 1]) rect_dst = [[min_x, min_y], [min_x, max_y], [max_x, max_y], [max_x, min_y]] # -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. # Homography calculation: H, _ = findHomography(array(rect_src), array(rect_dst)) src = float32(X[:, 0:2]).reshape(-1, 1, 2) # w = H_31 * src[i].x + H_32 * src[i].y + H_33 * 1 # Perspective Warp (src-->dst): # dst[i].x = (H_11 * src[i].x + H_12 * src[i].y + H_13 * 1) / w dst = perspectiveTransform(src, H).astype( int) # dst[i].y = (H_21 * src[i].x + H_22 * src[i].y + H_23 * 1) / w # Update marks coordinates: for mark in possible_marks_list: for k in range(len(X)): if X[k, 0] == mark.intCenterX_r and X[k, 1] == mark.intCenterY_r: mark.intCenterX_r = int(dst[k, 0][0]) mark.intCenterY_r = int(dst[k, 0][1]) # -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. debug("Perspective: Option=%d" % option_num, debugMode) debug( "Perspective: Rect_Src: p0=%s, p1=%s, p2=%s, p3=%s" % (rect_src[0], rect_src[1], rect_src[2], rect_src[3]), debugMode) debug( "Perspective: Rect_Dst: p0=%s, p1=%s, p2=%s, p3=%s" % (rect_dst[0], rect_dst[1], rect_dst[2], rect_dst[3]), debugMode) if debugMode: debug("Perspective Homography Matrix (H):", True) print(H) debug("Perspective SRC points (marks):", True) print(X[:, 0:2].T) debug("Perspective DST points (~H*SRC):", True) print(dst[:, 0].T) return rect_src, rect_dst
def find_possible_marks(frame_thresh, MinPixelWidth, MaxPixelWidth, MinPixelHeight, MaxPixelHeight, MinAspectRatio, MaxAspectRatio, MinPixelArea, MaxPixelArea, MinExtent, MaxExtent, MaxDrift, perspectiveMode, FindContoursMode, HoughParams, debugMode=False): """ Find all possible bracelet marks (finds all contours that could be representing marks) """ # Initialization: possible_marks_list = [] frame_thresh_copy = frame_thresh.copy() # Find all contours in the image: contours = [] if FindContoursMode == "Legacy": contours, _ = findContours(frame_thresh_copy, RETR_LIST, CHAIN_APPROX_SIMPLE) elif FindContoursMode == "Hough": circles = HoughCircles( image=frame_thresh_copy, # 8-bit, single channel image method= HOUGH_GRADIENT, # Defines the method to detect circles in images dp=HoughParams[0] if HoughParams[0] > 0 else 1, # Large dp values --> smaller accumulator array minDist=HoughParams[1] if HoughParams[1] > 0 else 60, # Min distance between the detected circles centers param1=HoughParams[2] if HoughParams[2] > 0 else 50, # Gradient value used to handle edge detection param2=HoughParams[3] if HoughParams[3] > 0 else 18, # Accumulator thresh val (smaller = more circles) minRadius=HoughParams[4] if HoughParams[4] > 0 else 20, # Minimum size of the radius (in pixels) maxRadius=HoughParams[5] if HoughParams[5] > 0 else 50 # Maximum size of the radius (in pixels) ) if circles is not None: for i in circles[0, :]: contours.append(circle_to_contour(i, 50, 0.7)) else: error("Unsupported FindContoursMode mode: %s" % FindContoursMode) # Create contours image: height, width = frame_thresh_copy.shape frame_contours = zeros((height, width, 3), uint8) drawContours(frame_contours, contours, -1, Colors.white) # Foreach contour, check if it describes a possible character: possible_marks_cntr = 0 for i in range(0, len(contours)): # Register the contour as a possible character (+calculate intrinsic metrics): possible_mark = PossibleMark(contours[i], MinPixelWidth, MaxPixelWidth, MinPixelHeight, MaxPixelHeight, MinAspectRatio, MaxAspectRatio, MinPixelArea, MaxPixelArea, MinExtent, MaxExtent) # If contour is a possible char, increment count of possible chars and add to list of possible chars: if possible_mark.check_if_possible_mark(): possible_marks_cntr += 1 possible_marks_list.append(possible_mark) if debugMode: print(possible_mark, possible_marks_cntr) if len(possible_marks_list) == 0: return possible_marks_list, 0 # Remove outliers in a PCA scheme, i.e. possible marks which are too faraway from the group or interiors: possible_marks_wo_outliers = remove_outliers(possible_marks_list, MaxDrift, debugMode) # Rotation and Perspective alignments: rotation_angle_deg = 0 if len(possible_marks_wo_outliers) > 0: # Rotation Alignment (SVD decomposition): rotation_angle_deg, centroid = rotation_alignment( possible_marks_wo_outliers, debugMode) # Perspective Alignment (Homography+PerspectiveWarp): possible_marks_final = deepcopy(possible_marks_wo_outliers) rect_src, rect_dst = perspective_alignment(possible_marks_final, perspectiveMode, rotation_angle_deg, debugMode) # -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. if debugMode: frame_possible_marks = zeros((height, width, 3), uint8) for possible_mark in possible_marks_wo_outliers: drawContours(frame_possible_marks, [possible_mark.contour], 0, Colors.white) frame_possible_marks[possible_mark.intCenterY - 3:possible_mark.intCenterY + 3, possible_mark.intCenterX - 3:possible_mark.intCenterX + 3, 2] = 255 frame_possible_marks[possible_mark.intCenterY_r - 3:possible_mark.intCenterY_r + 3, possible_mark.intCenterX_r - 3:possible_mark.intCenterX_r + 3, 0] = 255 for possible_mark in possible_marks_final: frame_possible_marks[possible_mark.intCenterY_r - 3:possible_mark.intCenterY_r + 3, possible_mark.intCenterX_r - 3:possible_mark.intCenterX_r + 3, 1:3] = 255 putText(frame_possible_marks, "Original", (10, 30), FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2) putText(frame_possible_marks, "Rotation fix (SVD)", (10, 70), FONT_HERSHEY_SIMPLEX, 1, (255, 0, 0), 2) putText(frame_possible_marks, "Centroid", (10, 110), FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2) putText(frame_possible_marks, "Perspective fix", (10, 150), FONT_HERSHEY_SIMPLEX, 1, (0, 255, 255), 2) if perspectiveMode == 1: frame_possible_marks = polylines(frame_possible_marks, array([rect_src]), True, (255, 0, 0), 1, LINE_AA) frame_possible_marks = polylines(frame_possible_marks, array([rect_dst]), True, (0, 255, 255), 1, LINE_AA) if len(frame_possible_marks) > 0: X_xc, X_yc = centroid frame_possible_marks[X_yc - 3:X_yc + 3, X_xc - 3:X_xc + 3, 1] = 255 debug("Amount of detected contours: %d" % len(contours), True) debug("Amount of possible marks: %d" % possible_marks_cntr, True) debug( "Amount of possible marks w/o outliers: %d" % len(possible_marks_wo_outliers), True) debug("Rotation: %.2f" % rotation_angle_deg, True) imwrite("img_contours_all.jpg", frame_contours) imwrite("img_possible_marks_.jpg", frame_possible_marks) return possible_marks_final, rotation_angle_deg
def main(_argv): print("Start") info("OpenCV version: " + CV_VERSION) # Default parameters: args = Struct( ImageFile= "/Users/shahargino/Documents/ImageProcessing/Bracelet_decoder/Database/180717/24.png", PreprocessCvcSel="V", PreprocessMode="Legacy", PreprocessGaussKernel=(5, 5), PreprocessThreshBlockSize=19, PreprocessThreshweight=7, PreprocessMorphKernel=(3, 3), PreprocessMedianBlurKernel=13, PreprocessCannyThr=80, imgEnhancementEn=False, MinPixelWidth=7, MaxPixelWidth=30, MinPixelHeight=7, MaxPixelHeight=30, MinAspectRatio=0.6, MaxAspectRatio=2.5, MinPixelArea=150, MaxPixelArea=600, MinExtent=0.4, MaxExtent=0.9, MaxDrift=2.5, MarksRows=3, MarksCols=10, ROI=(0, 0), PerspectiveMode=0, FindContoursMode="Legacy", HoughParams=(-1, -1, -1, -1, -1, -1), debugMode=False) # -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. # User-Arguments parameters (overrides Defaults): try: opts, user_args = getopt(_argv, "hvi:", [ "PreprocessCvcSel=", "PreprocessMode=", "PreprocessGaussKernel=", "PreprocessThreshBlockSize=", "PreprocessThreshweight=", "PreprocessMorphKernel=", "PreprocessMedianBlurKernel=", "PreprocessCannyThr=", "ROI=", "MinPixelWidth=", "MaxPixelWidth=", "MinPixelHeight=", "MaxPixelHeight=", "MinAspectRatio=", "MaxAspectRatio=", "MinPixelArea=", "MaxPixelArea=", "MinExtent=", "MaxExtent=", "MaxDrift=", "MarksRows=", "MarksCols=", "imgEnhancementEn", "PerspectiveMode=", "FindContoursMode=", "HoughParams=", "debug", "version" ]) for opt, user_arg in opts: if opt == '-h': usage() exit() elif opt in "-i": args.ImageFile = user_arg elif opt in "--PreprocessCvcSel": args.PreprocessCvcSel = user_arg elif opt in "--PreprocessMode": args.PreprocessMode = user_arg elif opt in "--PreprocessGaussKernel": args.PreprocessGaussKernel = literal_eval(user_arg) elif opt in "--PreprocessThreshBlockSize": args.PreprocessThreshBlockSize = int(user_arg) elif opt in "--PreprocessThreshweight": args.PreprocessThreshweight = int(user_arg) elif opt in "--PreprocessMorphKernel": args.PreprocessMorphKernel = literal_eval(user_arg) elif opt in "--PreprocessMedianBlurKernel": args.PreprocessMedianBlurKernel = int(user_arg) elif opt in "--PreprocessCannyThr": args.PreprocessCannyThr = int(user_arg) elif opt in "--ROI": args.ROI = literal_eval(user_arg) elif opt in "--MinPixelWidth": args.MinPixelWidth = float(user_arg) elif opt in "--MaxPixelWidth": args.MaxPixelWidth = float(user_arg) elif opt in "--MinPixelHeight": args.MinPixelHeight = float(user_arg) elif opt in "--MaxPixelHeight": args.MaxPixelHeight = float(user_arg) elif opt in "--MinAspectRatio": args.MinAspectRatio = float(user_arg) elif opt in "--MaxAspectRatio": args.MaxAspectRatio = float(user_arg) elif opt in "--MinPixelArea": args.MinPixelArea = float(user_arg) elif opt in "--MaxPixelArea": args.MaxPixelArea = float(user_arg) elif opt in "--MinExtent": args.MinExtent = float(user_arg) elif opt in "--MaxExtent": args.MaxExtent = float(user_arg) elif opt in "--MaxDrift": args.MaxDrift = float(user_arg) elif opt in "--MarksRows": args.MarksRows = int(user_arg) elif opt in "--MarksCols": args.MarksCols = int(user_arg) elif opt in "--imgEnhancementEn": args.imgEnhancementEn = True elif opt in "--PerspectiveMode": args.PerspectiveMode = int(user_arg) elif opt in "--FindContoursMode": args.FindContoursMode = user_arg elif opt in "--HoughParams": args.HoughParams = literal_eval(user_arg) elif opt in "--debug": args.debugMode = True elif opt in "--version" or opt == '-v': info("BraceletDecoder version: %s" % __version__) exit() except GetoptError as e: error(str(e)) usage() exit(2) # -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. -- .. # Load input image: frame_orig = imread(args.ImageFile) height, width, _ = frame_orig.shape # Create a working environment (debugMode): if args.debugMode: envpath = datetime.now().strftime( "results_%d%m%y_%H%M%S_") + args.ImageFile.split('/')[-1].replace( '.', '_') if not path.exists(envpath): makedirs(envpath) cwd = getcwd() chdir(envpath) # Resizing preparations: if args.PreprocessMode == "Legacy": resizingVec = (1600, 1200) if (width < height): resizingVec = resizingVec[::-1] elif args.PreprocessMode == "BlurAndCanny": resizingVec = (1120, 840) else: error("Unsupported PreprocessMode mode: %s" % args.PreprocessMode) # Resizing and ROI cropping: if args.PreprocessMode == "Legacy": imgResized = resize(frame_orig, resizingVec) imgCropped = crop_roi_from_image(imgResized, args.ROI) image = imgCropped elif args.PreprocessMode == "BlurAndCanny": imgCropped = crop_roi_from_image(frame_orig, args.ROI) imgResized = resize(imgCropped, resizingVec) image = imgResized # Image enhancement: if (args.imgEnhancementEn): imgEnhanced = imageEnhancement(image, 2, (8, 8), 3, args.debugMode) else: imgEnhanced = image # Preprocess: frame_gray, frame_thresh = preprocess( imgEnhanced, args.PreprocessCvcSel, args.PreprocessMode, args.PreprocessGaussKernel, args.PreprocessThreshBlockSize, args.PreprocessThreshweight, args.PreprocessMorphKernel, args.PreprocessMedianBlurKernel, args.PreprocessCannyThr) # Find bracelet marks: possible_marks, rotation_angle = find_possible_marks( frame_thresh, args.MinPixelWidth, args.MaxPixelWidth, args.MinPixelHeight, args.MaxPixelHeight, args.MinAspectRatio, args.MaxAspectRatio, args.MinPixelArea, args.MaxPixelArea, args.MinExtent, args.MaxExtent, args.MaxDrift, args.PerspectiveMode, args.FindContoursMode, args.HoughParams, args.debugMode) # Encode marks: code = decode_marks(possible_marks, args.MarksRows, args.MarksCols, frame_thresh.shape, rotation_angle, args.debugMode) info("Code = %s" % code) if args.debugMode: imwrite("frame_orig.jpg", draw_roi(frame_orig, args.ROI)) imwrite("frame_gray.jpg", frame_gray) imwrite("frame_thresh.jpg", frame_thresh) # Restore path: chdir(cwd)