Sagar Bharadwaj commited on
Commit
7fef374
·
1 Parent(s): d6f71e3

Made changes to denoising

Browse files
colorbynumber/config.py CHANGED
@@ -1,8 +1,17 @@
1
  default_config = {
2
  # If True, the image will be denoised after simplification.
3
  "denoise": True,
4
-
5
- # Higher values will result in more aggressive denoising.
 
 
 
 
 
 
 
 
 
6
  "denoise_h": 200,
7
 
8
  # Padding around the borders of the image.
@@ -26,7 +35,7 @@ default_config = {
26
  "border_color": (181, 181, 181),
27
 
28
  # Font for the numbers shown in color islands.
29
- "font_size": 0.3,
30
  "font_color": (140, 140, 140),
31
- "font_thickness": 1,
32
  }
 
1
  default_config = {
2
  # If True, the image will be denoised after simplification.
3
  "denoise": True,
4
+
5
+ # Determines the order of denoising.
6
+ # Options: "before_simplify", "after_simplify"
7
+ "denoise_order": "before_simplify",
8
+
9
+ # Type of denoising to be used.
10
+ # Options: "fastNlMeansDenoisingColored", "gaussianBlur", "blur"
11
+ "denoise_type": "gaussianBlur",
12
+ # Size of the kernel used for gaussian blur.
13
+ "blur_size": 51,
14
+ # h parameter for fastNlMeansDenoisingColored.
15
  "denoise_h": 200,
16
 
17
  # Padding around the borders of the image.
 
35
  "border_color": (181, 181, 181),
36
 
37
  # Font for the numbers shown in color islands.
38
+ "font_size": 1,
39
  "font_color": (140, 140, 140),
40
+ "font_thickness": 2,
41
  }
colorbynumber/main.py CHANGED
@@ -7,27 +7,38 @@ from .gen_islands import GenerateIslands
7
  from .numbered_islands import create_numbered_islands
8
 
9
  class ColorByNumber:
10
- def __init__(self, image_path, color_list, config = default_config):
 
 
11
  """
12
  Args:
13
  image_path: Path to the image file.
14
  color_list: List of colors in (R, G, B) format.
15
  config: Dictionary of configuration parameters (optional).
16
  """
 
 
 
17
  self.image_path = image_path
18
- self.color_list = color_list
19
  self.config = config
 
 
20
 
21
- def create_color_by_number(self):
22
  image = cv.imread(self.image_path)
23
  image = cv.cvtColor(image, cv.COLOR_BGR2RGB)
24
  self.image = image
25
 
26
- simplified_image, indices_color_choices = simplify_image(
 
 
27
  image=self.image,
28
  color_list=self.color_list,
 
29
  config=self.config
30
  )
 
 
 
31
  self.simplified_image = simplified_image
32
 
33
  generate_islands_obj = GenerateIslands(indices_color_choices)
 
7
  from .numbered_islands import create_numbered_islands
8
 
9
  class ColorByNumber:
10
+ def __init__(self, image_path,
11
+ color_list = None, num_colors = None,
12
+ config = default_config):
13
  """
14
  Args:
15
  image_path: Path to the image file.
16
  color_list: List of colors in (R, G, B) format.
17
  config: Dictionary of configuration parameters (optional).
18
  """
19
+ assert color_list is not None or num_colors is not None, \
20
+ "Either color_list or num_colors must be provided."
21
+
22
  self.image_path = image_path
 
23
  self.config = config
24
+ self.color_list = color_list
25
+ self.num_colors = num_colors
26
 
 
27
  image = cv.imread(self.image_path)
28
  image = cv.cvtColor(image, cv.COLOR_BGR2RGB)
29
  self.image = image
30
 
31
+ def create_color_by_number(self):
32
+
33
+ simplified_image, indices_color_choices, color_list = simplify_image(
34
  image=self.image,
35
  color_list=self.color_list,
36
+ num_colors=self.num_colors,
37
  config=self.config
38
  )
39
+ # Assigning the color_list to the one returned by simplify_image
40
+ # because if it was initially None, it would have been assigned a value.
41
+ self.color_list = color_list
42
  self.simplified_image = simplified_image
43
 
44
  generate_islands_obj = GenerateIslands(indices_color_choices)
colorbynumber/simplify_image.py CHANGED
@@ -31,19 +31,51 @@ def _choose_closest_colors(image, color_list):
31
 
32
  return simplified_image, indices_color_choices
33
 
34
- def _denoise_image(image, h):
35
- denoised_image = cv.fastNlMeansDenoisingColored(
36
- src = image.astype(np.uint8),
37
- dst = None,
38
- h = h,
39
- hColor = h,
40
- templateWindowSize = 7,
41
- searchWindowSize = 21
42
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
43
  return denoised_image
44
 
45
  def simplify_image(image,
46
- color_list,
 
47
  config = default_config,
48
  ):
49
  """
@@ -57,16 +89,36 @@ def simplify_image(image,
57
  Returns:
58
  A copy of the image with all colors replaced with the closest color in the list.
59
  """
60
- denoise = config["denoise"]
61
- denoise_h = config["denoise_h"]
 
 
 
 
 
 
 
 
 
 
 
 
62
 
63
- simplified_image, indices_color_choices = _choose_closest_colors(image, color_list)
64
- if denoise:
65
  # Denoising after simplifying image as denoising original image need not reduce the
66
  # number of colors islands and also removed some key features from the original image.
67
- simplified_image = _denoise_image(simplified_image, denoise_h)
 
 
 
 
 
68
 
69
  # Simplying image again as denoising may have introduced new colors.
70
- simplified_image, indices_color_choices = _choose_closest_colors(simplified_image, color_list)
 
 
 
71
 
72
- return simplified_image, indices_color_choices
 
31
 
32
  return simplified_image, indices_color_choices
33
 
34
+ def _kmeans_simplify_image(image, num_colors):
35
+ Z = image.reshape((-1,3))
36
+
37
+ # convert to np.float32
38
+ Z = np.float32(Z)
39
+
40
+ # define criteria, number of clusters(K) and apply kmeans()
41
+ criteria = (cv.TERM_CRITERIA_EPS + cv.TERM_CRITERIA_MAX_ITER, 10, 1.0)
42
+ K = num_colors
43
+ ret,label,center=cv.kmeans(Z,K,None,criteria,10,cv.KMEANS_RANDOM_CENTERS)
44
+
45
+ # Now convert back into uint8, and make original image
46
+ center = np.uint8(center)
47
+ res = center[label.flatten()]
48
+ res = res.reshape((image.shape))
49
+
50
+ simplified_image = res
51
+ indices_color_choices = label.reshape((image.shape[:2])) + 1
52
+ color_list = center
53
+
54
+ return simplified_image, indices_color_choices, color_list
55
+
56
+ def _denoise_image(image, h, denoise_type, blur_size = None):
57
+ if denoise_type == "fastNlMeansDenoisingColored":
58
+ denoised_image = cv.fastNlMeansDenoisingColored(
59
+ src = image.astype(np.uint8),
60
+ dst = None,
61
+ h = h,
62
+ hColor = h,
63
+ templateWindowSize = 7,
64
+ searchWindowSize = 21
65
+ )
66
+ elif denoise_type == "gaussianBlur":
67
+ kernel = (blur_size, blur_size)
68
+ denoised_image = cv.GaussianBlur(image, kernel, 0)
69
+
70
+ elif denoise_type == "blur":
71
+ kernel = (blur_size, blur_size)
72
+ denoised_image = cv.blur(image, kernel)
73
+
74
  return denoised_image
75
 
76
  def simplify_image(image,
77
+ color_list = None,
78
+ num_colors = None,
79
  config = default_config,
80
  ):
81
  """
 
89
  Returns:
90
  A copy of the image with all colors replaced with the closest color in the list.
91
  """
92
+ if config["denoise"] and (config["denoise_order"] == "before_simplify"):
93
+ image = _denoise_image(
94
+ image=image,
95
+ h = config["denoise_h"],
96
+ denoise_type = config["denoise_type"],
97
+ blur_size = config["blur_size"],
98
+ )
99
+
100
+ if color_list is None:
101
+ # Use kmeans to simplify the image to the specified number of colors.
102
+ simplified_image, indices_color_choices, color_list = _kmeans_simplify_image(image, num_colors)
103
+
104
+ else:
105
+ simplified_image, indices_color_choices = _choose_closest_colors(image, color_list)
106
 
107
+
108
+ if config["denoise"] and (config["denoise_order"] == "after_simplify"):
109
  # Denoising after simplifying image as denoising original image need not reduce the
110
  # number of colors islands and also removed some key features from the original image.
111
+ simplified_image = _denoise_image(
112
+ simplified_image,
113
+ h = config["denoise_h"],
114
+ denoise_type = config["denoise_type"],
115
+ blur_size = config["blur_size"],
116
+ )
117
 
118
  # Simplying image again as denoising may have introduced new colors.
119
+ simplified_image, indices_color_choices = _choose_closest_colors(
120
+ simplified_image,
121
+ color_list
122
+ )
123
 
124
+ return simplified_image, indices_color_choices, color_list