File size: 3,424 Bytes
54a7b7b
 
 
 
2ab378c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
54a7b7b
 
 
 
 
 
 
 
 
ef0641f
54a7b7b
 
 
 
 
ef0641f
 
 
 
 
 
 
 
 
 
54a7b7b
 
 
 
 
 
 
 
ef0641f
2ab378c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
import cv2
import numpy as np


def is_dark_bubble(image, threshold=100):
    """

    Determine if a bubble image is dark (black bubble with white text).

    

    Args:

        image: Input bubble image (BGR)

        threshold: Intensity threshold (below = dark bubble)

        

    Returns:

        bool: True if dark bubble, False if light bubble

    """
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    mean_intensity = np.mean(gray)
    return mean_intensity < threshold


def process_dark_bubble(image):
    """

    Processes a dark speech bubble (black with white text).

    Fills the bubble contents with black.

    

    Args:

        image (numpy.ndarray): Input dark bubble image.

        

    Returns:

        tuple: (processed_image, largest_contour)

    """
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    
    # For dark bubbles, find the dark region (invert threshold)
    _, thresh = cv2.threshold(gray, 50, 255, cv2.THRESH_BINARY_INV)
    
    contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    
    if not contours:
        h, w = image.shape[:2]
        largest_contour = np.array([[0, 0], [w, 0], [w, h], [0, h]], dtype=np.int32)
        image[:] = (0, 0, 0)  # Fill with black
        return image, largest_contour
    
    largest_contour = max(contours, key=cv2.contourArea)
    
    mask = np.zeros_like(gray)
    cv2.drawContours(mask, [largest_contour], -1, 255, cv2.FILLED)
    
    # Fill with black instead of white
    image[mask == 255] = (0, 0, 0)
    
    return image, largest_contour


def process_bubble(image):
    """

    Processes the speech bubble in the given image, making its contents white.



    Parameters:

    - image (numpy.ndarray): Input image.



    Returns:

    - image (numpy.ndarray):  Image with the speech bubble content set to white.

    - largest_contour (numpy.ndarray): Contour of the detected speech bubble (or None if not found).

    """
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    _, thresh = cv2.threshold(gray, 240, 255, cv2.THRESH_BINARY)

    contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    
    # Handle case when no contours found
    if not contours:
        # Return original image with a simple rectangular contour
        h, w = image.shape[:2]
        largest_contour = np.array([[0, 0], [w, 0], [w, h], [0, h]], dtype=np.int32)
        # Fill with white anyway
        image[:] = (255, 255, 255)
        return image, largest_contour
    
    largest_contour = max(contours, key=cv2.contourArea)

    mask = np.zeros_like(gray)
    cv2.drawContours(mask, [largest_contour], -1, 255, cv2.FILLED)

    image[mask == 255] = (255, 255, 255)

    return image, largest_contour


def process_bubble_auto(image, force_dark=False):
    """

    Automatically detect bubble type and process accordingly.

    

    Args:

        image: Input bubble image (BGR)

        force_dark: If True, treat as dark bubble regardless of detection

        

    Returns:

        tuple: (processed_image, contour, is_dark)

    """
    if force_dark or is_dark_bubble(image):
        processed, contour = process_dark_bubble(image)
        return processed, contour, True
    else:
        processed, contour = process_bubble(image)
        return processed, contour, False