Burke's algorithm is using for converting grayscale image to black and white version Source: Source: https://en.wikipedia.org/wiki/Dither Note: * Best results are given with threshold= ~1/2 * max greyscale value. * This implementation get RGB image and converts it to gr
| 7 | |
| 8 | |
| 9 | class Burkes: |
| 10 | """ |
| 11 | Burke's algorithm is using for converting grayscale image to black and white version |
| 12 | Source: Source: https://en.wikipedia.org/wiki/Dither |
| 13 | |
| 14 | Note: |
| 15 | * Best results are given with threshold= ~1/2 * max greyscale value. |
| 16 | * This implementation get RGB image and converts it to greyscale in runtime. |
| 17 | """ |
| 18 | |
| 19 | def __init__(self, input_img, threshold: int): |
| 20 | self.min_threshold = 0 |
| 21 | # max greyscale value for #FFFFFF |
| 22 | self.max_threshold = int(self.get_greyscale(255, 255, 255)) |
| 23 | |
| 24 | if not self.min_threshold < threshold < self.max_threshold: |
| 25 | msg = f"Factor value should be from 0 to {self.max_threshold}" |
| 26 | raise ValueError(msg) |
| 27 | |
| 28 | self.input_img = input_img |
| 29 | self.threshold = threshold |
| 30 | self.width, self.height = self.input_img.shape[1], self.input_img.shape[0] |
| 31 | |
| 32 | # error table size (+4 columns and +1 row) greater than input image because of |
| 33 | # lack of if statements |
| 34 | self.error_table = [ |
| 35 | [0 for _ in range(self.height + 4)] for __ in range(self.width + 1) |
| 36 | ] |
| 37 | self.output_img = np.ones((self.width, self.height, 3), np.uint8) * 255 |
| 38 | |
| 39 | @classmethod |
| 40 | def get_greyscale(cls, blue: int, green: int, red: int) -> float: |
| 41 | """ |
| 42 | >>> Burkes.get_greyscale(3, 4, 5) |
| 43 | 4.185 |
| 44 | >>> Burkes.get_greyscale(0, 0, 0) |
| 45 | 0.0 |
| 46 | >>> Burkes.get_greyscale(255, 255, 255) |
| 47 | 255.0 |
| 48 | """ |
| 49 | """ |
| 50 | Formula from https://en.wikipedia.org/wiki/HSL_and_HSV |
| 51 | cf Lightness section, and Fig 13c. |
| 52 | We use the first of four possible. |
| 53 | """ |
| 54 | return 0.114 * blue + 0.587 * green + 0.299 * red |
| 55 | |
| 56 | def process(self) -> None: |
| 57 | for y in range(self.height): |
| 58 | for x in range(self.width): |
| 59 | greyscale = int(self.get_greyscale(*self.input_img[y][x])) |
| 60 | if self.threshold > greyscale + self.error_table[y][x]: |
| 61 | self.output_img[y][x] = (0, 0, 0) |
| 62 | current_error = greyscale + self.error_table[y][x] |
| 63 | else: |
| 64 | self.output_img[y][x] = (255, 255, 255) |
| 65 | current_error = greyscale + self.error_table[y][x] - 255 |
| 66 | """ |