Module AmpliVision.src.objs.image.image_scanner
Functions
def display(image, t=100, title='ImageScanner')
Classes
class ImageScanner
-
Class to scan the image and return the scanned image.
Methods:
-
scan(image_og: np.ndarray) -> np.ndarray
- This method scans the image and returns the scanned image.
-
morphological_transform(gpu_img: cv.cuda_GpuMat) -> cv.cuda_GpuMat
- This method applies morphological transformations to highlight the grid. -
remove_background(img: np.ndarray) -> np.ndarray
- This method gets rid of the background through masking + grabcut algorithm. -
find_contours(gpu_img: cv.cuda_GpuMat) -> list
- This method finds the contours of the image. -
detect_corners(contours: list, img: np.ndarray) -> list
- This method detects the corners of the grid. -
perspective_transform(img: np.ndarray, corners: list) -> np.ndarray
- This method applies perspective transform to the image. -
find_dest(pts: list) -> list
- This method finds the destination coordinates. -
order_points(pts: list) -> list
- This method orders the points.
reference
<https://learnopencv.com/automatic-document-scanner-using-opencv/>
Expand source code
class ImageScanner: """ Class to scan the image and return the scanned image. ## Methods: - `scan(image_og: np.ndarray) -> np.ndarray` - This method scans the image and returns the scanned image. - `morphological_transform(gpu_img: cv.cuda_GpuMat) -> cv.cuda_GpuMat` - This method applies morphological transformations to highlight the grid. - `remove_background(img: np.ndarray) -> np.ndarray` - This method gets rid of the background through masking + grabcut algorithm. - `find_contours(gpu_img: cv.cuda_GpuMat) -> list` - This method finds the contours of the image. - `detect_corners(contours: list, img: np.ndarray) -> list` - This method detects the corners of the grid. - `perspective_transform(img: np.ndarray, corners: list) -> np.ndarray` - This method applies perspective transform to the image. - `find_dest(pts: list) -> list` - This method finds the destination coordinates. - `order_points(pts: list) -> list` - This method orders the points. ## reference https://learnopencv.com/automatic-document-scanner-using-opencv/ """ @classmethod def scan(cls, img_og: np.ndarray, do_white_balance: bool = False) -> np.ndarray: # Applying morphological transformations to highlight the grid # Utilizing the GPU for faster processing img = cls.hsv_threshold(img_og.copy(), 100) morph_img = MorphologicalTransformer.apply_morph(img) # Isolate the grid by removing background (Only works with CPU) no_bkg_img = BackgroundRemover.remove_background(morph_img) # Adjusting the image to highlight the grid contours = ContourFinder.find_contours(no_bkg_img) """ a = no_bkg_img.copy() cv.drawContours(a, contours, -1, (0, 255, 0), 3) display(a, 0) # """ corners = CornerDetector.detect_corners(contours, no_bkg_img) final_image = cls.perspective_transform(img_og, corners) if do_white_balance: final_image = WhiteBalanceAdjuster.adjust(final_image) return final_image # ----------------- Helper Functions ----------------- # @classmethod # function to turn everything that isnt kinda white to black def hsv_threshold(cls, img: np.ndarray, threshold: int) -> np.ndarray: # convert image to hsv hsv = cv.cvtColor(img, cv.COLOR_BGR2HSV) # define range of white color in HSV lower_white = np.array([0, 0, 255-threshold]) upper_white = np.array([255, threshold, 255]) # create a mask mask = cv.inRange(hsv, lower_white, upper_white) # apply the mask to the image res = cv.bitwise_and(img, img, mask=mask) return res @classmethod def perspective_transform(cls, img: np.ndarray, corners: list) -> np.ndarray: # REARRANGING THE CORNERS destination_corners = cls.find_dest(corners) # Getting the homography. (aka scanning the image) M = cv.getPerspectiveTransform(np.float32( corners), np.float32(destination_corners)) # Perspective transform using homography. final = cv.warpPerspective( img, M, (destination_corners[2][0], destination_corners[2][1]), flags=cv.INTER_LINEAR) return final @classmethod def find_dest(cls, pts: list) -> list: # DESTINATION COORDINATES (tl, tr, br, bl) = pts # Finding the maximum width. widthA = np.sqrt(((br[0] - bl[0]) ** 2) + ((br[1] - bl[1]) ** 2)) widthB = np.sqrt(((tr[0] - tl[0]) ** 2) + ((tr[1] - tl[1]) ** 2)) maxWidth = max(int(widthA), int(widthB)) # Finding the maximum height. heightA = np.sqrt(((tr[0] - br[0]) ** 2) + ((tr[1] - br[1]) ** 2)) heightB = np.sqrt(((tl[0] - bl[0]) ** 2) + ((tl[1] - bl[1]) ** 2)) maxHeight = max(int(heightA), int(heightB)) # Final destination co-ordinates. destination_corners = [[0, 0], [maxWidth, 0], [maxWidth, maxHeight], [0, maxHeight]] return cls.order_points(destination_corners) @staticmethod def order_points(pts: list) -> list: # Initialising a list of coordinates that will be ordered. rect = np.zeros((4, 2), dtype='float32') pts = np.array(pts) s = pts.sum(axis=1) # Top-left point will have the smallest sum. rect[0] = pts[np.argmin(s)] # Bottom-right point will have the largest sum. rect[2] = pts[np.argmax(s)] # Computing the difference between the points. diff = np.diff(pts, axis=1) # Top-right point will have the smallest difference. rect[1] = pts[np.argmin(diff)] # Bottom-left will have the largest difference. rect[3] = pts[np.argmax(diff)] # Return the ordered coordinates. return rect.astype('int').tolist()
Static methods
def find_dest(pts: list) ‑> list
def hsv_threshold(img: numpy.ndarray, threshold: int) ‑> numpy.ndarray
def order_points(pts: list) ‑> list
def perspective_transform(img: numpy.ndarray, corners: list) ‑> numpy.ndarray
def scan(img_og: numpy.ndarray, do_white_balance: bool = False) ‑> numpy.ndarray
-