Selaa lähdekoodia

fix(canvas): improve shape mode transitions and integrate EAN13 decoding

- Ensured canvas returns to EDIT mode after manual and AI-assisted shape creation
- Automatically switches back to CREATE mode after label dialog is closed
- Fixed toolbar becoming unresponsive after drawing finalization
- Integrated EAN13 barcode decoding and detection pipeline
- Streamlined prediction and shape finalization flow for consistency
- Refactored previous logic to resolve drawing/editing state issues
Tricolops 3 viikkoa sitten
vanhempi
commit
17ac69b22f

+ 0 - 1
examples/bbox_detection/labels.txt

@@ -1,4 +1,3 @@
 __ignore__
 _background_
 barcode
-tough_barcode

+ 223 - 157
labelme/ai/barcode_decode.py

@@ -23,7 +23,7 @@ class CodeSet:
     C = 3
 
 class Normalize:
-    def __init__(self, mean=(0.15525904, 0.15525904, 0.15525904), std=(0.12552188, 0.12552188, 0.12552188)):
+    def __init__(self, mean=(0.45, 0.45, 0.45), std=(0.24, 0.24, 0.24)):
         if not (isinstance(mean, (list, tuple)) and isinstance(std, (list, tuple))):
             raise ValueError("mean and std should be of type list or tuple.")
         self.mean = np.array(mean, dtype=np.float32)
@@ -69,7 +69,7 @@ class BarcodeDecodeModel:
     #     logger.debug("Pixmap set successfully in BarcodeDecodeModel.")
 
     def preprocess_image(self, image):
-        norm = Normalize(mean=(0.44948044,0.44948044,0.44948044), std=(0.22099442,0.22099442,0.22099442))
+        norm = Normalize(mean=(0.45, 0.45, 0.45), std=(0.24, 0.24, 0.24))
         resized_image = cv2.resize(image, (self.decoding_input_shape[3], self.decoding_input_shape[2]))
         resized_image = cv2.cvtColor(resized_image, cv2.COLOR_BGR2RGB)
         resized_image = norm(resized_image)
@@ -98,7 +98,7 @@ class BarcodeDecodeModel:
 
             # Create a mask of the same size as the original image
             # original_image = labelme.utils.img_qt_to_arr(self.pixmap.toImage())
-            cv2.imwrite(f"original_image{detection_idx + 1}.png", original_image)
+            # cv2.imwrite(f"original_image{detection_idx + 1}.png", original_image)
             mask = np.zeros(original_image.shape[:2], dtype=np.uint8)
             cv2.fillPoly(mask, [polygon], 255)  # Fill the polygon with white
 
@@ -109,7 +109,7 @@ class BarcodeDecodeModel:
             x, y, w, h = cv2.boundingRect(polygon)
             cropped_image_dec = masked_image[y:y+h, x:x+w]
 
-            cv2.imwrite(f"cropped_exact_{detection_idx + 1}.png", cropped_image_dec)
+            # cv2.imwrite(f"cropped_exact_{detection_idx + 1}.png", cropped_image_dec)
             logger.debug(f"cropped_exact image saved at  {detection_idx + 1}.")
              
             src_points = np.float32(points)
@@ -146,7 +146,7 @@ class BarcodeDecodeModel:
             aligned_barcode = cv2.warpPerspective(original_image, M, (width, height), flags=cv2.INTER_LINEAR)
 
             # Save the aligned barcode image
-            cv2.imwrite(f"decoding_barcode_{detection_idx + 1}.png", aligned_barcode)
+            # cv2.imwrite(f"decoding_barcode_{detection_idx + 1}.png", aligned_barcode)
             logger.debug(f"Aligned barcode saved at  {detection_idx + 1}.")
 
             # Normalize the image to scale pixel intensities to the range [0, 255]
@@ -159,38 +159,29 @@ class BarcodeDecodeModel:
             logger.debug(f"Saved normalized image for decoding : {detection_idx + 1}")
 
             # Run decoding model
-            confidence = None 
+            # confidence = None 
             # Run decoding on the original image
-            decoded_text, confidence = self.run_decoding(normalized_img, detection_idx, confidence)
-
-            # Validate checksum
-            if decoded_text:
-                checksum_valid, validated_result = self.validate_code128_checksum(decoded_text, detection_idx)
-                if checksum_valid:
-                    logger.debug(f"Validated result for detection {detection_idx + 1}: {validated_result}")
-                    return validated_result  # Return validated result
+            is_valid, decoded, decoded_text, msg, avg_conf, detection_idx = self.run_decoding(normalized_img, detection_idx)
+            # print(f"Valid: {is_valid}, detection_idx:{detection_idx + 1}, decoded:{decoded}, decoded_text:{decoded_text}, msg:{msg}, avg_conf:{avg_conf}")
+            
+            if not is_valid:
+                logger.warning(f"Decoding failed for detection {detection_idx + 1}: {msg}. Retrying with 180° rotation")
+                # Rotate image 180 degrees and retry
+                rotated_image = cv2.rotate(normalized_img, cv2.ROTATE_180)
+                is_valid, decoded, decoded_text, msg, avg_conf, detection_idx = self.run_decoding(rotated_image, detection_idx)
+                
+                if is_valid:
+                    logger.debug(f"Valid: {is_valid}, detection_idx:{detection_idx + 1}, decoded:{decoded}, decoded_text:{decoded_text}, msg:{msg}, avg_conf:{avg_conf}")
+                    return decoded
                 else:
-                    logger.error(f"Checksum validation failed for detection {detection_idx + 1}. Retrying with 180° rotation.")
-
-                    # Rotate image 180 degrees and retry
-                    rotated_image = cv2.rotate(normalized_img, cv2.ROTATE_180)
-                    decoded_text, confidence = self.run_decoding(rotated_image, detection_idx, confidence)
-
-                    # Validate checksum again
-                    if decoded_text:
-                        checksum_valid, validated_result = self.validate_code128_checksum(decoded_text, detection_idx)
-                        if checksum_valid:
-                            logger.debug(f"Validated result after rotation for detection {detection_idx + 1}: {validated_result}")
-                            return validated_result
-                        else:
-                            logger.error(f"Checksum validation failed after rotation for detection {detection_idx + 1}. Error: {validated_result}")
-                            return
-            return "Decoding failed"
+                    logger.warning(f"Decoding still failed after rotation for detection {detection_idx + 1}: {msg}")
+                    return ""
+            return decoded
         except Exception as e:
             logger.error(f"Error in decode_from_points: {e}")
             return "Error: Decoding failed"
         
-    def run_decoding(self, image_np, detection_idx, confidence):
+    def run_decoding(self, image_np, detection_idx):
         """Helper to run decoding on the given image."""
         preprocessed_img = self.preprocess_image(
             image_np
@@ -199,143 +190,218 @@ class BarcodeDecodeModel:
         output_tensor = decode_result['save_infer_model/scale_0.tmp_0']
         logger.debug(f"Output tensor shape: {output_tensor.shape}")
 
-        output_indices = np.argmax(output_tensor, axis=2)
-        output_probs = np.max(output_tensor, axis=2)
-        
+        output_indices_batch = np.argmax(output_tensor, axis=2)
+        output_probs_batch = np.max(output_tensor, axis=2)
+        # print(f"output_indices:{output_indices}")
         # Decode text from indices
-        decoded_text, confidence = self.decode_text(output_indices, output_probs, detection_idx)
-        logger.debug(f"Raw barcode: {decoded_text}, Confidence: {confidence:.2f}")
-        return decoded_text, confidence
-    
-    def decode_text(self, text_indices, text_probs, detection_idx):
-        """
-        Converts model output indices into text using the character dictionary.
-        Args:
-            text_indices (np.ndarray): Output indices from the decoding model.
-            text_probs (np.ndarray): Probabilities corresponding to the indices.
-        Returns:
-            tuple: Decoded text and its confidence score.
-        """
-        try:
-            max_index = len(self._characters) - 1
-            logger.debug(f"Loaded barcode dictionary with {len(self._characters)} characters.")
 
-            result_list = []
+        def preprocess_output_indices(output_indices_batch, output_probs_batch):
+            # Ensure it's a proper 2D numpy array
+            if output_indices_batch is None or len(output_indices_batch) == 0:
+                return False, "Empty output indices batch", None
+
+            first_row = output_indices_batch[0]
+            first_row_probs = output_probs_batch[0]
+            if first_row is None or len(first_row) == 0:
+                return False, "Empty output indices", None
+
+            sequence = first_row.tolist()
+            probs = first_row_probs.tolist()
+
+            # Step 1: Trim at first 0
+            if 0 in sequence:
+                zero_index = sequence.index(0)
+                cropped_indices = sequence[:zero_index]
+                cropped_probs = probs[:zero_index]
+            else:
+                cropped_indices = sequence
+                cropped_probs = probs
             
-            for batch_idx in range(text_indices.shape[0]):  # Loop through batches
-                char_list = []
-                conf_list = []
-                for step_idx in range(text_indices.shape[1]):  # Loop through sequence length
-                    char_idx = int(text_indices[batch_idx, step_idx])
-                    if char_idx > max_index:
-                        logger.warning(f"Index {char_idx} is out of bounds for dictionary size {len(self._characters)}")
-                        continue  # Skip invalid indices
-
-                    char = self._characters[char_idx]
-                    # print("char",char)
-                    if char == "</s>":  # End token
-                        break
-                    char_list.append(char)
-                    conf_list.append(text_probs[batch_idx, step_idx])
-
-                text = ''.join(char_list)
-                confidence = np.mean(conf_list) if conf_list else 0.0
-                result_list.append((text, confidence))
-
-            # Return the first result (assuming batch size of 1 for now)
-            return result_list[0] if result_list else ("", 0.0)
-        except Exception as e:
-            logger.error(f"Error in decode_text: {e}")
-            return "Error: Decoding failed", 0.0
-
-
-    def validate_code128_checksum(self, decoded_text, detection_idx):
-        # Convert characters to their corresponding Code 128 values using the index in _characters
-        # print(self._characters)
-        code128Values = [self._characters.index(char, 1) - 1 if char in self._characters[1:] else -1 for char in decoded_text]
-        logger.debug(f"code128Values:{code128Values}")
-        result = ""
-        err_msg = ""
-        currentCodeSet = CodeSet.B  # Default to Code Set B, assuming start code is included in decoded_text
+            index_prob_pairs = list(zip(cropped_indices, cropped_probs))
+
+
+            cropped = [x - 1 for x in cropped_indices]
+            # cropped = cropped_indices
+            # print(f"cropped: {cropped}")
+            # Step 2: Check for invalid trailing 107/108 after 0
+            if not any(val in (106, 107) for val in cropped):
+                return False, "Invalid: missin stop code (106 or 107) before first 0"
+
+            # Step 3: Truncate at second 108 if two 108s appear (EAN start/stop)
+            if cropped.count(108) >= 2:
+                print("got here")
+                first_108 = cropped.index(108)
+                # print(f"first_108:{first_108}")
+                second_108 = cropped.index(108, first_108 + 1)
+                # print(f"second_108:{second_108}")
+                cropped = cropped[:second_108 + 1]
+
+                # print(f"cropped: {cropped}")
+                index_prob_pairs = index_prob_pairs[:second_108 + 1]
+                # print(f": {index_prob_pairs}")
+            # Step 4: Check start code validity
+            start_code = cropped[0] if cropped else None
+            if start_code not in [103, 104, 105, 107]:
+                return False, f"Invalid start code: {start_code}"
+            return True, (cropped, index_prob_pairs)
+        decoded_text = ""
+        status, result_or_error = preprocess_output_indices(output_indices_batch, output_probs_batch)
+        # print(f"Raw barcode: {result_or_error}, status: {status}")
+        
+        if status == False:
+            print(f"msg: {result_or_error}")
+            decoded = "Decoding failed"
+            decoded_text = ""
+            msg = result_or_error
+            avg_conf = 0.0
+            return status, decoded, decoded_text, msg, avg_conf, detection_idx
+        else:
+            mapped_indices, conf_pairs = result_or_error
+            avg_conf = round(np.mean([conf for (_, conf) in conf_pairs]), 2)
+            # print(f"✅ Average confidence: {avg_conf:.3f}")
+            is_valid, barcode_value, msg, predicted_ean_digits_print = self.validate_checksum(mapped_indices)
+            # print(f"barcode_value: {barcode_value}, msg: {msg}, predicted_ean_digits_print: {predicted_ean_digits_print}, is_valid: {is_valid}")
+            if not is_valid:
+                decoded = "Decoding failed"
+                decoded_text = ""
+                msg = msg
+                avg_conf = 0.0
+                is_valid = is_valid
+                # logger.warning(f"{is_valid}, readable: {decoded}, raw: {decoded_text}, conf: {avg_conf}, format: {msg}")
+                return is_valid, decoded, decoded_text, msg, avg_conf, detection_idx
+            else:
+                if msg == "code128":
+                    decoded_text = ''.join([self._characters[idx] for idx in barcode_value])
+                    decoded = self.decode_code128(barcode_value)
+                    logger.debug(f"✅ {is_valid}, readable: {decoded}, raw: {decoded_text}, conf: {avg_conf}, format: {msg}")
+                else:
+                    # print(predicted_ean_digits_print)
+                    decoded_text = ''.join([self._characters[idx] for idx in predicted_ean_digits_print])
+                    decoded = ''.join(str(d) for d in barcode_value)                        
+                    logger.debug(f"✅ {is_valid}, readable: {decoded}, raw: {decoded_text}, conf: {avg_conf}, format: {msg}, detection_idx: {detection_idx}")   
+        return is_valid, decoded, decoded_text, msg, avg_conf, detection_idx
+    
+    def decode_code128(self, values):
+        # print(f"values:{values}")
+        values = values[:]  # avoid modifying original
+        start_code = values.pop(0)
+        checksum = values.pop(-1)
+        stop_code = values.pop(-1)
+
+        if start_code == 103:
+            current_set = 'A'
+        elif start_code == 104:
+            current_set = 'B'
+        elif start_code == 105:
+            current_set = 'C'
+        else:
+            return "Invalid start code"
 
+        decoded_chars = []
+        i = 0
+        while i < len(values):
+            val = values[i]
 
-        if code128Values[0] in [103, 104, 105]:
-            start_codes = {103: CodeSet.A, 104: CodeSet.B, 105: CodeSet.C}
-            currentCodeSet = start_codes[code128Values[0]]
-            # print("currentCodeSet",currentCodeSet)
-        else:
-            err_msg = f"No start code detected, first code is {code128Values[0]}"
-            return False, err_msg
-
-        checksum_expected = code128Values[-2]
-        # print("Expected checksum:", checksum_expected)
-
-        # Calculate the checksum using the formula
-        checksum_calculated = code128Values[0]  # Start with the start code value
-        for i, value in enumerate(code128Values[1:-2], start=1):  # Exclude stop code
-            weighted_value = value * i
-            checksum_calculated += weighted_value
-            # logger.debug(f"Position {i}, Value {value}, Weighted Value {weighted_value}, Running Checksum {checksum_calculated}")
-
-        checksum_calculated %= 103
-        logger.debug(f"Final Calculated Checksum (mod 103): {checksum_calculated}")
-        if checksum_calculated != checksum_expected:
-            err_msg = f"Invalid checksum value, supposed to be {checksum_calculated} but got {checksum_expected}"
-            return False, err_msg
-
-        # Verify the stop code
-        if code128Values[-1] != 106:
-            err_msg = "No valid stop code detected at the end of the sequence."
-            return False, err_msg
-        
-        result = ""
-        i = 1  # Start after the start code
-        while i < len(code128Values) - 2:  # Exclude checksum and stop code
-            value = code128Values[i]
-
-            # Handle special functions and code set shifts
-            if value == 102:  # FNC1 for GS1-128
-                logger.debug(f"Detected FNC1 at position {i}, treated as AI separator.")
-                # result += "|"  # Optional: Add a delimiter for AI parsing
+            # Handle switch codes
+            if val == 99:
+                current_set = 'C'
                 i += 1
                 continue
-            elif value == 99:  # Switch to Code Set C
-                currentCodeSet = CodeSet.C
-                logger.debug(f"Switched to Code Set C at position {i}")
+            elif val == 100:
+                current_set = 'B'
                 i += 1
                 continue
-            elif value == 100:  # Switch to Code Set B
-                currentCodeSet = CodeSet.B
-                logger.debug(f"Switched to Code Set B at position {i}")
+            elif val == 101:
+                current_set = 'A'
                 i += 1
                 continue
 
-            # Decode based on the current Code Set
-            if currentCodeSet == CodeSet.C:
-                result += f"{value:02}"
-                # logger.debug(f"Added Code Set C value {value:02} at position {i}")
-                i += 1
-            elif currentCodeSet == CodeSet.B:
-                if 0 <= value <= 95:
-                    char = self._characters[value + 1]  # Map using the single dictionary
-                    result += char
-                    # logger.debug(f"Added Code Set B char {char} at position {i}")
-                    i += 1
+            # Decode values
+            if current_set == 'C':
+                decoded_chars.append(f"{val:02d}")
+            else:
+                if 0 <= val < len(self._characters):
+                    decoded_chars.append(self._characters[val])
                 else:
-                    err_msg = f"Invalid Code Set B value: {value}"
-                    logger.error(err_msg)
-                    return False, err_msg
-            elif currentCodeSet == CodeSet.A:
-                if 0 <= value <= 95:
-                    char = self._characters[value + 1]  # Map using the single dictionary
-                    result += char
-                    # logger.debug(f"Added Code Set A char {char} at position {i}")
-                    i += 1
+                    decoded_chars.append('?')
+
+            i += 1
+
+        return ''.join(decoded_chars)
+
+    def validate_checksum(self, raw_values):
+        # raw_values = [characters.index(char, 1) - 1 if char in characters[1:] else -1 for char in decoded_text]
+        logger.debug(f"raw_values passed to validate_checksum: {raw_values}")
+        if raw_values[0] == 107:
+            logger.debug("Ean Barcode detected")
+            code_map_predicted = {
+                'C1': '107', 'C2': '108', '0A': '109', '1A': '110', '2A': '111', '3A': '112', '4A': '113',
+                '5A': '114', '6A': '115', '7A': '116', '8A': '117', '9A': '118', '0B': '119', '1B': '120',
+                '2B': '121', '3B': '122', '4B': '123', '5B': '124', '6B': '125', '7B': '126', '8B': '127',
+                '9B': '128', '0C': '129', '1C': '130', '2C': '131', '3C': '132', '4C': '133', '5C': '134',
+                '6C': '135', '7C': '136', '8C': '137', '9C': '138'
+            }
+            LEFT_PATTERN = (
+                "AAAAAA", "AABABB", "AABBAB", "AABBBA", "ABAABB",
+                "ABBAAB", "ABBBAA", "ABABAB", "ABABBA", "ABBABA"
+            )
+            reverse_code_map = {v: k for k, v in code_map_predicted.items()}
+            predicted_digits = [val for val in raw_values[1:-1] if val != 108]
+            # print(f"predicted_digits: {predicted_digits}")
+            mapped_keys = [reverse_code_map.get(str(val), f"UNK({val})") for val in predicted_digits]
+            # print(f"Mapped keys: {mapped_keys}")
+            detected_pattern = ''.join(k[-1] if len(k) == 2 else '?' for k in mapped_keys[:6])
+            # print(f"Detected_pattern: {detected_pattern}")
+            if detected_pattern in LEFT_PATTERN:
+                pattern_index = LEFT_PATTERN.index(detected_pattern)
+                # print(f"pattern_index: {pattern_index}")
+            else:
+                
+                return False, None, "wrong pattern", None
+            predicted_ean_value = ''.join(k[0] if len(k) == 2 and k[0].isdigit() else '?' for k in mapped_keys)
+            # print(f"predicted_ean_value:{predicted_ean_value}")
+            ean13 = str(pattern_index) + predicted_ean_value[:12]
+            # print(f"ean13 base:{ean13}")
+            if len(ean13) != 13 or not ean13.isdigit():
+                logger.warning(f"Invalid Ean value needs to be 13 digits")
+                return False, None, "Invalid EAN-13 base", None
+            else:
+                def calculate_ean13_checksum(ean13):
+                    digits = [int(d) for d in ean13]
+                    even_sum = sum(digits[i] for i in range(0, 12, 2))
+                    odd_sum = sum(digits[i] for i in range(1, 12, 2))
+                    total = even_sum + odd_sum * 3
+                    # print(f"total:{total}")
+                    return (10 - (total % 10)) % 10
+            
+                calculated_ean_checksum = calculate_ean13_checksum(ean13)
+                # print(f"calculated_ean_checksum:{calculated_ean_checksum}")
+                predicted_ean_checksum = predicted_ean_value[-1]
+                # print(f"predicted_ean_checksum:{predicted_ean_checksum}")
+                if str(predicted_ean_checksum) != str(calculated_ean_checksum):
+                    logger.warning(f"Invalid ean 13 checksum value, supposed to be {calculated_ean_checksum}")
+                    return False, None, f"Invalid ean 13 checksum: expected {calculated_ean_checksum}", None
                 else:
-                    err_msg = f"Invalid Code Set A value: {value}"
-                    logger.error(err_msg)
-                    return False, err_msg
-
-        # logger.debug(f"Decoded result after processing: {result}")
-        # logger.debug(f"Result indices for {detection_idx + 1}: {result_indices}")
-        return True, result       
+                    ean_list = [int(char) for char in ean13]
+                    predicted_ean_digits_print = raw_values
+                return True, ean_list, "ean13", predicted_ean_digits_print
+        else:
+            logger.debug("Code128 Barcode detected")
+            # dict_converted_to_code128_dict = [x - 1 for x in raw_values]
+            # print("dict_converted_to_code128_dict", dict_converted_to_code128_dict)
+            code128 = raw_values
+            # print("code128code128", code128)
+            start_code = code128[0]
+            
+            predicted_code128_checksum = code128[-2]
+            # print("predicted_code128_checksum", predicted_code128_checksum)
+            code128_base = code128[1:-2]
+            # print(code128_base)
+            weighted_sum = sum(val * (i +1) for i, val in enumerate(code128_base))
+            calculated_128_checksum =(start_code + weighted_sum) % 103
+            logger.debug(f"predicted_code128_checksum: {predicted_code128_checksum}, calculated_128_checksum: {calculated_128_checksum}")
+            if predicted_code128_checksum != calculated_128_checksum:
+                logger.warning(f"Invalid checksum value, supposed to be {calculated_128_checksum} but model predicted {predicted_code128_checksum}")
+                return False, None, "Invalid checksum value", None
+            
+            return True, code128, "code128", None

+ 6 - 6
labelme/ai/barcode_detect.py

@@ -11,7 +11,7 @@ from qtpy import QtGui
 
 
 class Normalize:
-    def __init__(self, mean=(0.15525904, 0.15525904, 0.15525904), std=(0.12552188, 0.12552188, 0.12552188)):
+    def __init__(self, mean=(0., 0., 0.), std=(0.1, 0.1, 0.1)):
         if not (isinstance(mean, (list, tuple)) and isinstance(std, (list, tuple))):
             raise ValueError("mean and std should be of type list or tuple.")
         self.mean = np.array(mean, dtype=np.float32)
@@ -43,9 +43,9 @@ class BarcodeDetectModel:
             self.segmentation_sess = self.ie.compile_model(model=self.segmentation_net, device_name="CPU")
         
         self._lock = threading.Lock()
-        self.input_height = 640  # Input shape for detection model (example size)
-        self.input_width = 640
-        self.segmentation_input_shape = (1, 3, 128, 256)  # Input shape for segmentation model
+        self.input_height = 800  # Input shape for detection model (example size)
+        self.input_width = 800
+        self.segmentation_input_shape = (1, 3, 160, 320)  # Input shape for segmentation model
         self._image_embedding_cache = collections.OrderedDict()
         self._max_cache_size = 10
         self.normalize = Normalize()  # Normalization instance
@@ -69,7 +69,7 @@ class BarcodeDetectModel:
         if for_segmentation:
             # Resize image to segmentation model input size
             logger.debug(f"Preprocessing image for segmentation: {image.shape}")
-            norm = Normalize(mean=(0.447365,0.447365,0.447365), std=(0.17667491,0.17667491,0.17667491))
+            norm = Normalize(mean=(0.5,0.5,0.5), std=(0.5,0.5,0.5))
             resized_image = cv2.resize(image, (self.segmentation_input_shape[3], self.segmentation_input_shape[2]))  # Width, Height
             resized_image = cv2.cvtColor(resized_image, cv2.COLOR_BGR2RGB)
             resized_image = norm(resized_image)  # Normalize for segmentation model
@@ -128,7 +128,7 @@ class BarcodeDetectModel:
 
         outputs = output_array  # shape [50,6]
         point_list = []
-        thresh_hold = 0.7
+        thresh_hold = 0.5
 
         for bbox_info in outputs:
             score = bbox_info[1]

+ 2 - 1
labelme/utils/__init__.py

@@ -33,9 +33,10 @@ import os
 def load_barcode_dict():
     """Load the barcode dictionary from the utils folder."""
     dict_path = os.path.join(os.path.dirname(__file__), "barcode_dict.txt")
+    # print(f"dict_path: {dict_path}")
     try:
         with open(dict_path, "r", encoding="utf-8") as f:
             characters = f.read().splitlines()
-        return ["</s>"] + characters  # Add special character
+        return characters  # Add special character
     except Exception as e:
         raise FileNotFoundError(f"Error loading barcode_dict.txt: {e}")

+ 33 - 1
labelme/utils/barcode_dict.txt

@@ -104,4 +104,36 @@ z
 ø
 Ñ
 ú
+€
+ÿ

+ 8 - 8
labelme/widgets/canvas.py

@@ -872,7 +872,7 @@ class Canvas(QtWidgets.QWidget):
             print(manual_points)
             logger.debug(f"Manually drawn points: {manual_points}")
             self.detect_and_segment(manual_points=manual_points)
-            self.mode = self.EDIT  # Or any appropriate mode to disable drawing behavior
+            # self.mode = self.EDIT  # Or any appropriate mode to disable drawing behavior
             return
         if self.createMode == "ai_polygon":
             # convert points to polygon by an AI model
@@ -916,7 +916,9 @@ class Canvas(QtWidgets.QWidget):
                 self.shapes.append(drawing_shape)
                 self.storeShapes()
                 self.update()
+                self.setEditing(True)
                 self.newShape.emit()
+                self.setEditing(False)
             # self.pred_bbox_points = None
             # self.draw_pred = False
             # self.detect_and_segment()  # Process the next detection
@@ -935,7 +937,6 @@ class Canvas(QtWidgets.QWidget):
         self.setHiding(False)
         self.newShape.emit()
         self.update()
-
     def closeEnough(self, p1, p2):
         # d = distance(p1 - p2)
         # m = (p1-p2).manhattanLength()
@@ -1198,7 +1199,7 @@ class Canvas(QtWidgets.QWidget):
                 else: 
                     rotated = False
                 # Save crop image
-                cv2.imwrite(f"cropped_image_{detection_idx + 1}.png", cropped_image)
+                # cv2.imwrite(f"cropped_image_{detection_idx + 1}.png", cropped_image)
                 logger.debug(f"Saved cropped image for detection {detection_idx + 1}: {cropped_image.shape}")
 
                 # logger.debug(f"Cropped image shape for detection {detection_idx + 1}: {cropped_image.shape}")
@@ -1245,7 +1246,7 @@ class Canvas(QtWidgets.QWidget):
                 else:
                     mask = scaled_mask
                 
-                cv2.imwrite(f"scaled_segmentation_mask_{detection_idx + 1}.png", mask)
+                # cv2.imwrite(f"scaled_segmentation_mask_{detection_idx + 1}.png", mask)
                 logger.debug(f"Saved segmentation mask for detection {detection_idx + 1}.")
                 
                 # Step 7: Find contours
@@ -1267,7 +1268,7 @@ class Canvas(QtWidgets.QWidget):
                     # Step 1: Draw the rotated rectangle on the cropped image
                     cropped_with_rects = cropped_image.copy()
                     cv2.drawContours(cropped_with_rects, [box_points], -1, (0, 255, 0), 2)
-                    cv2.imwrite(f"cropped_with_rects_{detection_idx + 1}.png", cropped_with_rects)
+                    # cv2.imwrite(f"cropped_with_rects_{detection_idx + 1}.png", cropped_with_rects)
                     logger.debug(f"Saved cropped image with rectangles for detection {detection_idx + 1}.")
 
                     if rotated:
@@ -1291,16 +1292,15 @@ class Canvas(QtWidgets.QWidget):
                                     original_image = original_image
                                 )
                                 logger.debug(f"Decoded output for detection {detection_idx + 1}: {decoded_output}")
+                                
                                 #passed to popup through app.py and label_dailog.py
                                 self.decoded_barcode = decoded_output
-                                # (Optional) Use the decoded output for updating UI or further processing
-                                # Example: Print or log the decoded text
-                                # print(f"Decoded output: {decoded_output}")
                             except Exception as e:
                                 logger.error(f"Error during decoding for bbox points {bbox_points}: {e}")
                     
                     ## pass each shape points to decode function here, do the decodign and give back the output here and print the output
                     if self.pred_bbox_points:
+                        
                         self.draw_pred = True
                         self.finalise()
                     else: