| 1 | import cv2 as cv
 | 
  
    | 2 | import numpy as np
 | 
  
    | 3 | from ConfigureReader import ConfigureReader
 | 
  
    | 4 | from ImageReader import ImageReader
 | 
  
    | 5 | 
 | 
  
    | 6 | CR = ConfigureReader()
 | 
  
    | 7 | IR = ImageReader()
 | 
  
    | 8 | 
 | 
  
    | 9 | ##
 | 
  
    | 10 | # @brief
 | 
  
    | 11 | #
 | 
  
    | 12 | # This class calculates blended image.
 | 
  
    | 13 | # This class is made by Minghao, Shiva, Son, and Vaibhav, Doxygened by Rikuto Momoi
 | 
  
    | 14 | #
 | 
  
    | 15 | 
 | 
  
    | 16 | 
 | 
  
    | 17 | class CalculateDisplayImage(object):
 | 
  
    | 18 | 
 | 
  
    | 19 |     # The constructor
 | 
  
    | 20 |     def __init__(self):
 | 
  
    | 21 |         projector_image_width = CR.getProjectorImageWidth()
 | 
  
    | 22 |         projector_distance = CR.getProjectorDistance()
 | 
  
    | 23 |         self.gamma = CR.getGamma()
 | 
  
    | 24 |         self.method = CR.getMethod()
 | 
  
    | 25 |         self.np_left = IR.getImage()[0]
 | 
  
    | 26 |         self.np_right = IR.getImage()[1]
 | 
  
    | 27 |         self.overlap_pixels = round(
 | 
  
    | 28 |             self.np_left.shape[1]*(projector_image_width - projector_distance)/projector_image_width)
 | 
  
    | 29 | 
 | 
  
    | 30 |     ##
 | 
  
    | 31 |     # @brief
 | 
  
    | 32 |     # Get the blended image
 | 
  
    | 33 |     # @param corrected_tuple contains the gamma corrected image left and right
 | 
  
    | 34 |     # @return RGB formatted blended images
 | 
  
    | 35 |     def getDisplayImage(self, corrected_tuple):
 | 
  
    | 36 |         corrected_left, corrected_right = corrected_tuple
 | 
  
    | 37 |         # to RGB
 | 
  
    | 38 |         blended_left = np.rint(corrected_left*255).astype(np.uint8)
 | 
  
    | 39 |         blended_right = np.rint(corrected_right*255).astype(np.uint8)
 | 
  
    | 40 |         # save images
 | 
  
    | 41 |         cv.imwrite('src/blended_left.jpg', blended_left)
 | 
  
    | 42 |         cv.imwrite('src/blended_right.jpg', blended_right)
 | 
  
    | 43 |         return blended_left, blended_right
 | 
  
    | 44 | 
 | 
  
    | 45 |     ##
 | 
  
    | 46 |     # @brief 
 | 
  
    | 47 |     # Control the texture of the mask
 | 
  
    | 48 |     # @param distance is the distance from the start point of the target overlap region
 | 
  
    | 49 |     # @param monotonicity is the monotonicity of the intensity function
 | 
  
    | 50 |     # @return Intensity control value
 | 
  
    | 51 |     def intensityController(self, distance, monotonicity):
 | 
  
    | 52 | 
 | 
  
    | 53 |         if monotonicity == 'linearly_increase':
 | 
  
    | 54 |             return -distance/self.overlap_pixels + 1
 | 
  
    | 55 |         elif monotonicity == 'linearly_decrease':
 | 
  
    | 56 |             return distance/self.overlap_pixels
 | 
  
    | 57 |         elif monotonicity == 'nonlinearly_increase':
 | 
  
    | 58 |             return -np.power(distance/self.overlap_pixels, 2) + 1
 | 
  
    | 59 |         elif monotonicity == 'nonlinearly_decrease':
 | 
  
    | 60 |             return np.power(distance/self.overlap_pixels, 2)
 | 
  
    | 61 | 
 | 
  
    | 62 |     ##
 | 
  
    | 63 |     # @brief  
 | 
  
    | 64 |     # Generates masks
 | 
  
    | 65 |     # @param mask is a white mask with the same size of the image
 | 
  
    | 66 |     # @param direction is the direction of the mask
 | 
  
    | 67 |     # @return gradient masks (in linear case)
 | 
  
    | 68 |     def maskGenerator(self, mask, direction):
 | 
  
    | 69 | 
 | 
  
    | 70 |         for columns in range(mask.shape[1]-self.overlap_pixels-1, mask.shape[1]):
 | 
  
    | 71 |             mask[0, columns, :] *= self.intensityController(
 | 
  
    | 72 |                 columns-(mask.shape[1]-self.overlap_pixels-1), monotonicity=self.method+'ly_increase')
 | 
  
    | 73 |         # replacement is more efficient than multiplication
 | 
  
    | 74 |         for rows in range(1, mask.shape[0]):
 | 
  
    | 75 |             mask[rows, :, :] = mask[0, :, :]
 | 
  
    | 76 | 
 | 
  
    | 77 |         if direction == 'left':
 | 
  
    | 78 |             return mask
 | 
  
    | 79 |         elif direction == 'right':
 | 
  
    | 80 |             # flip direction of mask to right
 | 
  
    | 81 |             return np.flip(mask, axis=1)
 | 
  
    | 82 | 
 | 
  
    | 83 |     ##
 | 
  
    | 84 |     # @brief
 | 
  
    | 85 |     # Get gamma corrected image
 | 
  
    | 86 |     # @param img is the image blended with masks
 | 
  
    | 87 |     # @param direction is the direction of the image
 | 
  
    | 88 |     # @param gamma is the gamma value
 | 
  
    | 89 |     # @return gamma corrected numpy array
 | 
  
    | 90 |     def gammaCorrection(self, img, direction, gamma):
 | 
  
    | 91 | 
 | 
  
    | 92 |         if direction == 'left':
 | 
  
    | 93 |             for rows in range(img.shape[0]):
 | 
  
    | 94 |                 for columns in range(img.shape[1]-self.overlap_pixels-1, img.shape[1]):
 | 
  
    | 95 |                     img[rows][columns][:] *= np.power(self.intensityController(
 | 
  
    | 96 |                         columns-(img.shape[1]-self.overlap_pixels-1), monotonicity=self.method + 'ly_increase'), gamma)
 | 
  
    | 97 |             return img
 | 
  
    | 98 | 
 | 
  
    | 99 |         elif direction == 'right':
 | 
  
    | 100 |             for rows in range(img.shape[0]):
 | 
  
    | 101 |                 for columns in range(self.overlap_pixels-1):
 | 
  
    | 102 |                     img[rows][columns][:] *= np.power(
 | 
  
    | 103 |                         self.intensityController(columns, monotonicity=self.method + 'ly_decrease'), gamma)
 | 
  
    | 104 |             return img
 | 
  
    | 105 | 
 | 
  
    | 106 |     ##
 | 
  
    | 107 |     # @brief  
 | 
  
    | 108 |     # Calculate the image to display
 | 
  
    | 109 |     # @return final blended image left and right
 | 
  
    | 110 |     def calculate(self):
 | 
  
    | 111 |         # generate masks
 | 
  
    | 112 |         mask_left = self.maskGenerator(
 | 
  
    | 113 |             np.ones(self.np_left.shape), direction='left')
 | 
  
    | 114 |         mask_right = self.maskGenerator(
 | 
  
    | 115 |             np.ones(self.np_right.shape), direction='right')
 | 
  
    | 116 |         # blend images with masks
 | 
  
    | 117 |         with_mask_left = np.multiply(self.np_left, mask_left)
 | 
  
    | 118 |         with_mask_right = np.multiply(self.np_right, mask_right)
 | 
  
    | 119 |         # apply gamma correction
 | 
  
    | 120 |         corrected_left = self.gammaCorrection(
 | 
  
    | 121 |             with_mask_left, direction='left', gamma=self.gamma)
 | 
  
    | 122 |         corrected_right = self.gammaCorrection(
 | 
  
    | 123 |             with_mask_right, direction='right', gamma=self.gamma)
 | 
  
    | 124 |         return corrected_left, corrected_right
 |