# XXXv2_correct_skew_shadow ``` import numpy as np import cv2 from skimage.feature import canny from skimage.transform import hough_line, hough_line_peaks, rotate from skimage.color import rgb2gray class SkewDetect: def __init__(self, input_file=None, sigma=3.0, num_peaks=15): self.input_file = input_file self.sigma = sigma self.num_peaks = num_peaks def get_max_freq_elem(self, arr): max_arr = [] freqs = {} for i in arr: if i in freqs: freqs[i] += 1 else: freqs[i] = 1 sorted_keys = sorted(freqs, key=freqs.get, reverse=True) max_freq = freqs[sorted_keys[0]] for k in sorted_keys: if freqs[k] == max_freq: max_arr.append(k) return max_arr def compare_sum(self, value): if value >= 44 and value <= 46: return True else: return False @staticmethod def calculate_deviation(angle): angle_in_degrees = np.abs(angle) deviation = np.abs(np.pi / 4 - angle_in_degrees) return deviation def process_single_file(self): res = self.determine_skew(self.input_file) return res def determine_skew(self, img_file): img = cv2.cvtColor(img_file, cv2.COLOR_BGR2RGB) img = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY) edges = canny(img, sigma=self.sigma) h, a, d = hough_line(edges) _, ap, _ = hough_line_peaks(h, a, d,threshold = 0.25*np.max(h), num_peaks=self.num_peaks) if len(ap) == 0: return {"Image File": img_file, "Message": "Bad Quality"} # absolute_deviations = [self.calculate_deviation(k) for k in ap] # average_deviation = np.mean(np.rad2deg(absolute_deviations)) # ap_deg = [np.rad2deg(x) for x in ap] absolute_deviations = [] for k in ap: slope = np.tan(k) if abs(slope) > 8: deviation = self.calculate_deviation(k) absolute_deviations.append(deviation) average_deviation = np.mean(np.rad2deg(absolute_deviations)) ap_deg = [] for x in ap: slope = np.tan(x) if abs(slope) > 8: ap_deg.append(np.rad2deg(x)) bin_0_45 = [] bin_45_90 = [] bin_0_45n = [] bin_45_90n = [] for ang in ap_deg: deviation_sum = int(90 - ang + average_deviation) if self.compare_sum(deviation_sum): bin_45_90.append(ang) continue deviation_sum = int(ang + average_deviation) if self.compare_sum(deviation_sum): bin_0_45.append(ang) continue deviation_sum = int(-ang + average_deviation) if self.compare_sum(deviation_sum): bin_0_45n.append(ang) continue deviation_sum = int(90 + ang + average_deviation) if self.compare_sum(deviation_sum): bin_45_90n.append(ang) angles = [bin_0_45, bin_45_90, bin_0_45n, bin_45_90n] lmax = 0 for j in range(len(angles)): l = len(angles[j]) if l >= lmax: lmax = l maxi = j if lmax: ans_arr = self.get_max_freq_elem(angles[maxi]) ans_res = np.mean(ans_arr) else: ans_arr = self.get_max_freq_elem(ap_deg) ans_res = np.mean(ans_arr) data = { "Image File": img_file, "Average Deviation from pi/4": average_deviation, "Estimated Angle": ans_res, "Angle bins": angles} return data def shadow(img): blue,green,red = cv2.split(img) rgb_planes = [blue,green,red] result_planes = [] for plane in rgb_planes: dilated_img = cv2.dilate(plane, np.ones((7,7), np.uint8)) bg_img = cv2.medianBlur(dilated_img, 21) diff_img = 255 - cv2.absdiff(plane, bg_img) result_planes.append(diff_img) result = cv2.merge(result_planes) return result def process_image(img): ## shadow input_img = shadow(img) ## 翻轉 skew_obj = SkewDetect(input_img) origin_img = cv2.cvtColor(input_img, cv2.COLOR_BGR2RGB) res = skew_obj.process_single_file() angle = res['Estimated Angle'] if -45 <= angle <= 90: rot_angle = angle - 90 elif -90 <= angle < -45: rot_angle = 90 + angle else: rot_angle = angle - 90 rotated = rotate(origin_img, rot_angle, resize=True) rotated_gray = rgb2gray(rotated) image_rotated = cv2.cvtColor(np.uint8(rotated_gray * 255), cv2.COLOR_RGB2BGR) return image_rotated # if __name__ == '__main__': # img2=cv2.imread('img2.jpg') # img3=process_image(img2) # cv2.imwrite('img3.jpg',img3) # print('done') ```