Project

General

Profile

Actions

Codes

MainDisplay.py : To calculate blended image

import cv2 as cv
from CalculateDisplayImage import CalculateDisplayImage

CDI = CalculateDisplayImage()

##
# @brief
#
# This class displays blended images.
# This class is made by Vaibhav, Doxygened by Xu Minghao.
#

class MainDisplay(object):

    ##
    # @brief
    # Display the blended images.
    # @param img is the image blended with masks.
    def display(img):
        cv.imshow('img', img)
        cv.waitKey(0)
        cv.destroyAllWindows()

    # The constructor.
    def __init__(self):
        pass

    ## A class variable.
    # To store the blended images.
    res = CDI.getDisplayImage(CDI.calculate())

    display(res[0])
    # display(res[1])

CalculateDisplayImage.py : To calculate blended image

import cv2 as cv
import numpy as np
from ConfigureReader import ConfigureReader
from ImageReader import ImageReader

CR = ConfigureReader()
IR = ImageReader()

##
# @brief
#
# This class calculates blended image.
# This class is made by Minghao, Shiva, Son, and Vaibhav, Doxygened by Rikuto Momoi.
#

class CalculateDisplayImage(object):

    # The constructor
    def __init__(self):
        projector_image_width = CR.getProjectorImageWidth()
        projector_distance = CR.getProjectorDistance()
        self.image_width = CR.getImageWidth()
        self.image_height = CR.getImageHeight()
        self.gamma = CR.getGamma()
        self.method = CR.getMethod()
        self.np_left = IR.getImage()[0]
        self.np_right = IR.getImage()[1]
        self.overlap_pixels = round(
            self.image_width*(projector_image_width - projector_distance)/projector_image_width)

    ##
    # @brief
    # Get the blended image.
    # @param corrected_tuple contains the gamma corrected image left and right.
    # @return RGB formatted blended images.
    def getDisplayImage(self, corrected_tuple):
        corrected_left, corrected_right = corrected_tuple
        # to RGB
        blended_left = np.rint(corrected_left*255).astype(np.uint8)
        blended_right = np.rint(corrected_right*255).astype(np.uint8)
        # save images
        cv.imwrite('src/blended_left.jpg', blended_left)
        cv.imwrite('src/blended_right.jpg', blended_right)
        return blended_left, blended_right

    ##
    # @brief
    # Control the texture of the mask.
    # @param distance is the distance from the start point of the target overlap region.
    # @param monotonicity is the monotonicity of the intensity function.
    # @return Intensity control value.
    def intensityController(self, distance, monotonicity):

        if monotonicity == 'linearly_increase':
            return -distance/self.overlap_pixels + 1
        elif monotonicity == 'linearly_decrease':
            return distance/self.overlap_pixels
        elif monotonicity == 'nonlinearly_increase':
            return -np.power(distance/self.overlap_pixels, 2) + 1
        elif monotonicity == 'nonlinearly_decrease':
            return np.power(distance/self.overlap_pixels, 2)

    ##
    # @brief
    # Generates masks.
    # @param direction is the direction of the mask.
    # @return Gradient masks (in linear case).
    def maskGenerator(self, direction):

        # assume images have the same size
        mask = np.ones(self.np_left.shape)
        for columns in range(self.image_width-self.overlap_pixels-1, self.image_width):
            mask[0, columns, :] *= self.intensityController(
                columns-(self.image_width-self.overlap_pixels-1), monotonicity=self.method+'ly_increase')
        # replacement is more efficient than multiplication
        for rows in range(1, self.image_height):
            mask[rows, :, :] = mask[0, :, :]

        if direction == 'left':
            return mask
        elif direction == 'right':
            # flip direction of mask to right
            return np.flip(mask, axis=1)

    ##
    # @brief
    # Get gamma corrected image.
    # @param img is the image blended with masks.
    # @param direction is the direction of the image.
    # @param gamma is the gamma value.
    # @return Gamma corrected numpy array.
    def gammaCorrection(self, img, direction, gamma):

        if direction == 'left':
            for rows in range(self.image_height):
                for columns in range(self.image_width-self.overlap_pixels-1, self.image_width):
                    img[rows][columns][:] *= np.power(self.intensityController(
                        columns-(self.image_width-self.overlap_pixels-1), monotonicity=self.method + 'ly_increase'), gamma)
            return img

        elif direction == 'right':
            for rows in range(self.image_height):
                for columns in range(self.overlap_pixels-1):
                    img[rows][columns][:] *= np.power(
                        self.intensityController(columns, monotonicity=self.method + 'ly_decrease'), gamma)
            return img

    ##
    # @brief
    # Calculate the image to display.
    # @return final blended image left and right.
    def calculate(self):
        # generate masks
        mask_left = self.maskGenerator(
            direction='left')
        mask_right = self.maskGenerator(
            direction='right')
        # blend images with masks
        with_mask_left = np.multiply(self.np_left, mask_left)
        with_mask_right = np.multiply(self.np_right, mask_right)
        # apply gamma correction
        corrected_left = self.gammaCorrection(
            with_mask_left, direction='left', gamma=self.gamma)
        corrected_right = self.gammaCorrection(
            with_mask_right, direction='right', gamma=self.gamma)
        return corrected_left, corrected_right

    ## @var gamma
    # Gamma value.
    ## @var method
    # Method of intensity control.
    ## @var np_left
    # Normalized Numpy array of left image.
    ## @var np_right
    # Normalized Numpy array of right image.
    ## @var overlap_pixels
    # Overlap region width.
    ## @var image_height
    # Image height.
    ## @var image_width
    # Image width.

ConfigureReader.py : Initialize the values to process the edge-blending

from configparser import ConfigParser

##
# @brief
#
# This class reads initial values that will be needed to process the edge-blending.
# This class is made by Son and Minghao, Doxygened by Konatsu.
#

class ConfigureReader(object):

    # The constructor.
    def __init__(self):
        self.config = ConfigParser()
        self.config.read('config.ini')

    ##
    # @brief
    # Get split image height.
    # @return image height in int.
    def getImageWidth(self):
        return int(self.config['DEFAULT']['ImageWidth'])

    ##
    # @brief
    # Get split image width.
    # @return image width in int.
    def getImageHeight(self):
        return int(self.config['DEFAULT']['ImageHeight'])

    ##
    # @brief
    # Get distance between two projectors.
    # @return projector distance in float.
    def getProjectorDistance(self):
        return float(self.config['DEFAULT']['projector_distance'])

    ##
    # @brief
    # Get projected image width.
    # @return image width in float.
    def getProjectorImageWidth(self):
        return float(self.config['DEFAULT']['projector_image_width'])

    ##
    # @brief
    # Get gamma value.
    # @return gamma value in float.
    def getGamma(self):
        return float(self.config['DEFAULT']['gamma'])

    ##
    # @brief
    # Get edge-blending method.
    # @return method in string.
    def getMethod(self):
        return str(self.config['DEFAULT']['method'])

    ##
    # @brief
    # Get image path (image should be put inside src).
    # @return image path in string.
    def getImagePath(self):
        return 'src/' + str(self.config['DEFAULT']['ImageNameLeft']), 'src/' + str(self.config['DEFAULT']['ImageNameRight'])

    # @var config
    # The configuration file.

ImageReader.py : To read image and normalize them into numpy array tuple.

import cv2 as cv
import numpy as np
from ConfigureReader import ConfigureReader

CR = ConfigureReader()

##
# @brief
#
# This class reads images and normalize them into numpy array tuple.
# This class is made by Shiva, Doxygened by Rikuto Momoi
#

class ImageReader(object):

    # The constructer
    def __init__(self):
        pass

    ##
    # @brief 
    # Get image in a normalized numpy array
    # @return normalized numpy array
    def getImage(self):
        return np.array(cv.imread(CR.getImagePath()[0]))/255, np.array(cv.imread(CR.getImagePath()[1]))/255

Updated by Anonymous over 3 years ago · 6 revisions