def do_high_boost_filtering(pgm_filename, A): high_boost_filtered = spatially_filtered_fast(pgm_filename, high_boost_filter_kernel(A)) p1 = PGMImage(pgm_filename) high_boost_filtered.save(f"highboost-filtered-A{A}-{p1.name}")
def averaging_filtering(pgm_filename, mask_size): p = PGMImage(pgm_filename) k = Kernel(mask = [[1] * mask_size] * mask_size) p_averaging_filtered = averaging_filtered(pgm_filename, k, normalize=True) p_averaging_filtered.save(f"averaging_filtered-{mask_size}-{p.name}")
def median_filtering(pgm_filename, mask_size): p = PGMImage(pgm_filename) k = Kernel(mask = [[1] * mask_size] * mask_size) p_median_filtered = median_filtered(pgm_filename, k, normalize=True) p_median_filtered.save(f"median_filtered-{mask_size}-{p.name}")
def test_1_identity_filter(): identity_filter = Kernel(mask=[[1]]) pgm_filename = "images/lenna.pgm" expected = PGMImage(pgm_filename) actual = spatially_filtered_fast(pgm_filename, identity_filter) assert expected.pixels == actual.pixels
def do_unsharp_masking(pgm_filename: str) -> PGMImage: p_orig = PGMImage(pgm_filename) p_lowpass = spatially_filtered_fast(pgm_filename, smoothing_kernel) p_lowpass.save(f"lowpass-{p_lowpass.name}") p_highpass = p_orig - p_lowpass p_highpass.save(f"highpass-{p_highpass.name}") return p_highpass
def spatially_filtered_fast(pgm_filename: str, k: Kernel, normalize=False, truncate=False) -> PGMImage: p = PGMImage(pgm_filename) def c_2d_arr_from_pyobj(pyobj: List[List[int]], arr_type, row_type): c_2d_arr = arr_type() for i in range(len(pyobj)): row = row_type() for j in range(len(pyobj[0])): row[j] = pyobj[i][j] c_2d_arr[i] = c_pointer_to(row) return c_2d_arr def c_2d_arr_empty(arr_type, row_type, rows, cols): c_2d_arr = arr_type() for i in range(rows): row = row_type() for j in range(cols): row[j] = 0 c_2d_arr[i] = c_pointer_to(row) return c_2d_arr C_PGMRowT = c_char * p.cols C_PGMImageT = PointerT(C_PGMRowT) * p.rows C_KernelRowT = c_double * k.cols C_KernelT = PointerT(C_KernelRowT) * k.rows c_p = c_2d_arr_from_pyobj(p.pixels, C_PGMImageT, C_PGMRowT) c_p_2 = c_2d_arr_empty( PointerT(c_double * p.cols) * p.rows, c_double * p.cols, p.rows, p.cols) c_k = c_2d_arr_from_pyobj(k.mask, C_KernelT, C_KernelRowT) spatialfilter = ctypes.cdll.LoadLibrary("./spatialfilter.so") spatialfilter.apply_spatial_filter(c_p, c_p_2, p.cols, p.rows, c_k, k.rows, k.cols) p2 = PGMImage(pgm_filename) for i in range(p.rows): p2.pixels[i] = [c_p_2[i][0][j] for j in range(p2.cols)] if normalize: p2.normalize_intensity_values() if truncate: p2.truncate_intensity_values() return p2
def smooth_image_averaging(pgm_filename): p = PGMImage(pgm_filename) p_average_7 = spatially_filtered(pgm_filename, average_matrix_7, truncate=True) p_average_7.save(f"smoothed_averaging-7-{p.name}") p_average_15 = spatially_filtered(pgm_filename, average_matrix_15, truncate=True) p_average_15.save(f"smoothed_averaging-15-{p.name}")
def spatially_filtered(pgm_filename: str, k: Kernel, normalize=False, truncate=False) -> PGMImage: """ Return an image with the spatial filter `k` applied to it. :param pgm_filename file name of image to perform filter on :param k a kernel of the spatial filter we want to apply """ p1, p2 = PGMImage(pgm_filename), PGMImage(pgm_filename) for i in range(p1.rows): new_row = [] for j in range(p1.cols): pxl = 0 for s in range(k.rows): for t in range(k.cols): x, y = i - int(k.rows / 2) + s, j - int(k.cols / 2) + t # Pad edges of the image with zeros if x < 0 or x >= p1.rows or y < 0 or y >= p1.cols: orig_image_x_y = 0 else: orig_image_x_y = p1.pixels[x][y] pxl += orig_image_x_y * k.mask[s][t] new_row.append(pxl) p2.pixels[i] = new_row if normalize: p2.normalize_intensity_values() if truncate: p2.truncate_intensity_values() return p2
def do_correlation(pgm_filename, mask_filename): pmask = PGMImage(mask_filename) def correlation_kernel(p: PGMImage): mask = [] for row in p.pixels: mask.append([b for b in row]) return Kernel(mask) k = correlation_kernel(pmask) p2: PGMImage = spatially_filtered_fast(pgm_filename, k) p2.save(f"correlated-to-{pmask.name}-{p2.name}")
def smooth_image_gaussian(pgm_filename): p = PGMImage(pgm_filename) p_gaussian = spatially_filtered(pgm_filename, gaussian_matrix_7, normalize=True, truncate=False) p_gaussian.save(f"smoothed_gaussian-7-{p.name}") p_gaussian = spatially_filtered(pgm_filename, gaussian_matrix_15, normalize=True, truncate=False) p_gaussian.save(f"smoothed_gaussian-15-{p.name}")
def square_image(sq_sz): canvas = np.zeros((512, 512)) for i in range(sq_sz): for j in range(sq_sz): x = int(256 - (sq_sz / 2) + i) y = int(256 - (sq_sz / 2) + j) canvas[x][y] = 255 p = PGM.PGMImage('lenna.pgm') p.pixels = canvas p.rows = p.cols = 512 p.truncate() p.save(f'square-{sq_sz}.pgm') return p
def adjust_quantization_and_save(img_name: str, quantization: int): try: p = PGMImage(img_name) print(f"Adjusting quantization of {img_name} to {quantization}") p.quantization = quantization for i in range(p.rows): # Normalize, quantize, and cast to byte string p.pixels[i] = b"".join([ bytes([int((int(px) / 256) * quantization)]) for px in p.pixels[i] ]) p.save(f"images/quantized-{quantization}-{p.name}") except IOError: pass
def do_sharpening(pgm_filename): p1 = PGMImage(pgm_filename) # Prewitt filtering p1_x_filtered_prewitt = spatially_filtered_fast(pgm_filename, prewitt_kernel_x) p1_x_filtered_prewitt.save(f"gradient-magnitude-prewitt-x-{p1.name}") p1_y_filtered_prewitt = spatially_filtered_fast(pgm_filename, prewitt_kernel_y) p1_y_filtered_prewitt.save(f"gradient-magnitude-prewitt-y-{p1.name}") p2 = p1_x_filtered_prewitt + p1_y_filtered_prewitt p2.save(f"isotropic-gradient-magnitude-prewitt-{p1.name}") p3 = p1 - p2 p3.save(f"prewitt-sharpened-{p1.name}") # Sobel filtering p1_x_filtered_sobel = spatially_filtered_fast(pgm_filename, sobel_kernel_x) p1_x_filtered_sobel.save(f"gradient-magnitude-sobel-x-{p1.name}") p1_y_filtered_sobel = spatially_filtered_fast(pgm_filename, sobel_kernel_y) p1_y_filtered_sobel.save(f"gradient-magnitude-sobel-y-{p1.name}") p2 = p1_x_filtered_sobel + p1_y_filtered_sobel p2.save(f"isotropic-gradient-magnitude-sobel-{p1.name}") p3 = p1 - p2 p3.save(f"sobel-sharpened-{p1.name}") # Laplace filtering p1_laplace_filtered = spatially_filtered_fast(pgm_filename, laplacian_kernel) p1_laplace_filtered.save(f"laplacian-gradient-magnitude-{p1.name}") p2 = p1 - p1_laplace_filtered p2.save(f"laplacian-sharpened-{p1.name}")
def transformer_of(p: PGMImage) -> List[int]: """ Calculate a transformer for histogram equalization. The transformer is a list, indexed by intensity values, whose values represent the output intensity required for an equalized histogram, given an input histogram. :param p image to equalize the histogram of """ histogram = p.get_histogram(normed=True) L = p.quantization # Number of distinct grey levels # Calculate histogram transformer T_r = [0] * (L + 1) # len([0, L]) = L + 1 for i in range(len(histogram)): if i == 0: T_r[i] = L * histogram[i] else: T_r[i] = ((T_r[i - 1] / L) + histogram[i]) * L # Discretize T_r by taking the ceil return [min(int(t_r + 1), 255) for t_r in T_r]
def equalize_histogram(img_name: str, visualize_results: bool): p = PGMImage(img_name) T_r = transformer_of(p) p2 = PGMImage(img_name) # Transform the image according to T_r for i in range(len(p2.pixels)): p2.pixels[i] = b"".join(bytes([T_r[b]]) for b in p2.pixels[i]) p2.save(f"equalized-{p2.name}") if visualize_results: p.show_histogram(title=f"Histogram of {p.name} before equalization") p2.show_histogram(title=f"Histogram of {p2.name} after equalization")
def specify_histogram(img_name, specified_img_name, visualize_results=True): p1, p2 = PGMImage(img_name), PGMImage(specified_img_name) T_r = transformer_of(p1) G_z = transformer_of(p2) def inverted_histogram(h: List[int]) -> List[int]: G_i = [0] * len(h) for h_i in h: G_i[h_i] = h_i # Populate missing values last_nonzero_intensity = 0 for i in range(len(h)): if G_i[i] != 0: last_nonzero_intensity = G_i[i] else: G_i[i] = last_nonzero_intensity return G_i G_inverse_z = inverted_histogram(G_z) p3 = PGMImage(img_name) for i in range(len(p3.pixels)): p3.pixels[i] = b"".join( bytes([G_inverse_z[T_r[b]]]) for b in p3.pixels[i]) p3.save(f"specified-to-{p2.name}-{p1.name}") if visualize_results: p1.show_histogram() p2.show_histogram() p3.show_histogram( title=f"Histogram of {p1.name}, specified to {p2.name}")
p = PGM('zigzag.pgm') a = np.fft.fft2(p.pixels) ashift = np.fft.fftshift(a) magnitude_spectrum = 20 * np.log(np.abs(ashift)) # Set Plot properties # plt.scatter(a.real, a.imag) # plt.axis([-1_000_000, 1_000_000, -400_000, 400_000]) plt.imshow(20 * np.log(np.abs(np.fft.fftshift(a))), cmap='gray') # Display plot plt.show() from PGM import PGMImage p = PGMImage('lenna.pgm') pxls = p.pixels import copy fft_out_c = copy.deepcopy(pxls) fft_out_py = np.fft.fft2(pxls) fft_out_c = [my_cfft(row) for row in fft_out_c] for i in range(p.cols): col = [row[i] for row in fft_out_c] col = my_cfft(col) for j in range(p.rows): fft_out_c[j][i] = col[j]