def find_offset(fname_path, xy=None, meter_id=None, code=None): # if not fname_path.endswith('008_v.jpg'): # return if xy is None: xy = (978, 516) xy = tuple(map(int, xy)) image0 = cv.imread(fname_path) # , cv.IMREAD_GRAYSCALE) # Debug.log_image('image0') qr_list = QrDecode.get_all_qrs(image0) if not len(qr_list): logger.error(f' not found any qr mark in {fname_path}') return 9999, 9999 # if len(qr_list) > 1: # Debug.error(f' more than one ({len(qr_list)}) marks in {fname_path}') # qr_list = sorted(qr_list, key=lambda x: x.box.area(), reverse=True) qr_list = [qr_mark for qr_mark in qr_list if code == qr_mark.code.decode('utf-8')] if not len(qr_list): logger.error(f'not found mark for code {code} in file {fname_path}') return 9999, 9999 anchor = qr_list[0].anchor img = image0.copy() cv.circle(img, xy, 10, colors.BGR_YELLOW, 2) KeyPoint.draw_list(anchor, ['kp', 'kp1', 'kp2'], img) Debug.log_image(f'{meter_id}_offs_target', img) offset = KeyPoint.xy_to_offset(xy, anchor) print(f'file {fname_path}: code={qr_list[0].code} offset={offset[0]:.5f},{offset[1]:.5f}') return offset
def __init__(self, anchors): # anchors --> candidate_areas: self.image = anchors.image self.anchors = anchors.anchors self.candidate_qr_areas = [] for ind in range(len(self.anchors)): anchor = self.anchors[ind] kp, kp1, kp2 = anchor # # if Cfg.area_preparing_method == 'warp_affine': # todo remove, it's just a test # # # Extract subregion of qr_area from the entire image # # qr_area = self.get_subimage_warp(anchor, self.image) # # Debug.log_image('area_after_warp', qr_area) # else: # method=='subimage': find 4th corner -> stretch -> fit_to_shape -> crop # find 4th point kp4 = kp.find_4th_corner(kp1, kp2) # 3 squares --> 4th square # rectangle of 4 square centers --> qr_area rectangle corners = KeyPoint.expand(kp1, kp, kp2, kp4, Cfg.expand_ratio) # correct corners which are out of image (after stretching) qr_area_keypoints = KeyPoint.fit_to_shape(corners, self.image.shape) # Extract subregion of qr_area from the entire image qr_area, center, size, theta = self.get_subimage(qr_area_keypoints, self.image) # make otsu binarization if ordered in Cfg if Cfg.use_otsu_threshold: blur = cv.GaussianBlur(qr_area, (5, 5), 0) ret, candidate_area = cv.threshold(blur, 0, 255, cv.THRESH_BINARY + cv.THRESH_OTSU) else: candidate_area = qr_area # set axis info (cross_x,cross_y,xaxis_angle) Debug.log_image(f'finished_{ind}', candidate_area) self.candidate_qr_areas.append((candidate_area, center, size, theta))
def __init__(self, image, qr_ancor): self.image = image self.qr_anchor = qr_ancor self.center = KeyPoint(size=0, x=int(mean([kp.x for kp in self.qr_anchor])), y=int(mean([kp.x for kp in self.qr_anchor]))) self.radius = max([self.center.distance(kp) for kp in qr_ancor]) self.qr_roi = self.image[self.center.x - self.radius:self.center.x + self.radius, self.center.y - self.radius:self.center.y + self.radius] blur = cv.GaussianBlur(self.qr_roi, (5, 5), 0) ret, self.thresh_otsu = cv.threshold(blur, 0, 255, cv.THRESH_BINARY + cv.THRESH_OTSU) ret2, self.image_thresholded = cv.threshold(image, self.thresh_otsu, 255, cv.THRESH_BINARY) self.mask = np.zeros(self.image_thresholded.shape, dtype=np.uint8) self.mask[self.center.x - self.radius:self.center.x + self.radius, self.center.y - self.radius:self.center.y + self.radius] = 255 Debug.log_image('mask') self.image_finished = self.image_thresholded self.image_thresholded[self.mask == 0] = 255 Debug.log_image('image_finished')
def draw_anchors(self): for ind in range(len(self.anchors)): anchor = self.anchors[ind] img = cv.cvtColor(self.image, cv.COLOR_GRAY2BGR) for kp in anchor: cv.circle(img, (kp.x, kp.y), kp.size, colors.BGR_RED, 2) anchor[0].draw_beam(anchor[1], ' ', img, colors.BGR_ORANGE) # angle>0 ==> kp1 is xaxis (I suppose) Debug.log_image(f'anchor_{ind}', img)
def draw_qr_area(self, image): if len(image.shape == 2): img_qr_area = cv.cvtColor(image, cv.COLOR_GRAY2BGR) else: img_qr_area = image.copy() for kp in self.qr_anchor: cv.circle(img_qr_area, (kp.x, kp.y), int(kp.size / 2), colors.BGR_GREEN, 1) cv.circle(img_qr_area, self.center, self.radius, colors.BGR_GREEN, 1) Debug.log_image('img_qr_area') return img_qr_area
def take_readings(fname_path_flir): # file --> db + files in images/date Debug.set_log_image_names(fname_path_flir) try: fi = FlirImage(fname_path_flir) except (ValueError, KeyError): logger.exception( f'error while flir-processing file {fname_path_flir}. Skipped.') return 0, None qr_mark_list = QrDecode.get_all_qrs(fi.visual_img) visual_img_copy = fi.visual_img.copy() thermal_img_copy = fi.thermal_img.copy() reading_cnt = 0 meter_ids = [] for qr_mark in qr_mark_list: meter_records = Db.get_meters_from_db(qr_mark.code) if meter_records is None: logger.info(f'qrs_to_readings: no equips for qr_mark {qr_mark}') continue for meter_id, offset_x, offset_y in meter_records: meter_ids.append(meter_id) if offset_x == 9999.: continue logger.debug(f'take readings: meter_id={meter_id}: ') reading = Reading(meter_id, (offset_x, offset_y), qr_mark, fi) if reading.temperature is None: logger.error( f'cannot create Reading ' f'for meter_id={meter_id} offset=({offset_x},{offset_y}) ' f'due to illegal coordinates after offset_to_xy()') continue if _GroupEquip.ready_to_analyze(event='readings_taken', meter_ids=meter_ids): Analyzer.run() reading.save_to_db() # reading.save_to_csv() # logger.debug(reading) reading.draw_visual(visual_img_copy) reading.draw_thermal(thermal_img_copy) Debug.log_image('visual_read', visual_img_copy) Debug.log_image('thermal_read', thermal_img_copy) reading_cnt += 1 return reading_cnt, meter_ids
def get_blob_keypoints(self): # input image --> list of blob keypoints params = cv.SimpleBlobDetector_Params() # Filter by Area. params.filterByArea = True params.minArea = MyMath.circle_area_by_diameter(Cfg.min_blob_diameter) # Set up the detector detector = cv.SimpleBlobDetector_create(params) # Detect blobs keypoints = detector.detect(self.image) # Draw detected blobs as red circles. # cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS ensures the size of the circle corresponds to the size of blob img_with_keypoints = cv.drawKeypoints(self.image, keypoints, np.array([]), colors.BGR_BLUE, cv.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS) Debug.log_image('img_with_keypoints', img_with_keypoints) blob_keypoints = KeyPointList(blob_detector_keypoints_list=keypoints) logger.debug(f'keypoints found:{blob_keypoints}') return blob_keypoints
def __init__(self, candidate_areas): self.image = candidate_areas.image self.areas = candidate_areas.candidate_qr_areas self.anchors = candidate_areas.anchors self.qr_decoded_marks = None # areas --> qr_decoded_marks: marks = [] for ind in range(len(self.areas)): area, center, size, theta = self.areas[ind] pyzbar_objs = pyzbar.decode(area) if not len(pyzbar_objs): continue if len(pyzbar_objs) > 1: logger.info(f'Multiple codes ({len(pyzbar_objs)}) found in area {ind}') # skip it, definitely they should be found separately continue mark = QrMark(pyzbar_objs[0], area, self.anchors[ind], ind, center, size, theta) if self.area_ratio(mark, area, ind) < Cfg.min_area_ratio: logger.debug(f'found box area ratio is too small relatively to CandidateArea. Skipped. ind={ind}') continue marks.append(mark) Debug.log_image(f'found_{ind}_{mark.code}', mark.draw_box(area)) # Debug.log_image(f'found_area_{ind}_{mark.code}', area) # duplicates rarely created if several triplets looks like anchor while referencing to the same qr code area # remove duplicates from marks: # for equal codes take one with the minimal area uniq_codes = list(set([m.code for m in marks])) # list of unique codes from marks code_minareas = [(c, min([m.box_area for m in marks if m.code == c])) for c in uniq_codes] # list of tuples (code, min area for all marks with this code) # get items from marks which have minimal area for each uniq code self.qr_decoded_marks = [m for m in marks if (m.code, m.box.area()) in code_minareas] logger.debug(f'decoded marks list after removing duplicates:{self.qr_decoded_marks}]')
def process_file(fname_path): image0 = cv.imread(fname_path, cv.IMREAD_GRAYSCALE) Debug.log_image('image0') qr_list = QrDecode.get_all_qrs(image0) found = len(qr_list) # cnt marks found return found