示例#1
0
def demosaicing_CFA_Bayer_bilinear(raw: RawImageInfo, output):
    """
    Bilinear Bayer CFA Demosaicing
    ==============================
    *Bayer* CFA (Colour Filter Array) bilinear demosaicing.
    References
    ----------
    -   :cite:`Losson2010c` : Losson, O., Macaire, L., & Yang, Y. (2010).
        Comparison of Color Demosaicing Methods. In Advances in Imaging and
        Electron Physics (Vol. 162, pp. 173-265). doi:10.1016/S1076-5670(10)62005-8
    """

    R_m, G_m, B_m = raw.masks_CFA_Bayer()
    CFA = raw.get_raw_data()

    H_G = np.float32(
        [[0, 1, 0],
         [1, 4, 1],
         [0, 1, 0]]) * 0.25

    H_RB = np.float32(
        [[1, 2, 1],
         [2, 4, 2],
         [1, 2, 1]]) * 0.25

    output[:, :, 2] = convolve(CFA * R_m, H_RB)
    output[:, :, 1] = convolve(CFA * G_m, H_G)
    output[:, :, 0] = convolve(CFA * B_m, H_RB)

    del R_m, G_m, B_m, H_RB, H_G
    return
示例#2
0
 def __init__(self, parmas, process_bar=None):
     self.old_pipeline = []
     self.pipeline = []
     self.params = parmas
     # img_list存储了pipeline中途所有的图像
     # img_list长度比pipeline长1
     self.img_list = [RawImageInfo()]
     self.process_bar = process_bar
     self.imglist_mutex = Lock()
     self.ispProcthread = ISPProc(self.params, self.img_list, self.imglist_mutex)
示例#3
0
 def pipeline_reset(self):
     """
     func: 重新开始一个pipeline,把以前的图像清除
     """
     if(len(self.img_list) > 1):
         self.imglist_mutex.acquire()
         self.img_list = [RawImageInfo()]
         self.imglist_mutex.release()
         self.old_pipeline = []
         self.pipeline = []
         return True
     return False
示例#4
0
    def __init__(self, name='RawImageEditor', parent=None):
        super().__init__(name, parent, Ui_ImageEditor(), need_processBar=True)

        self.scene = QGraphicsScene()
        self.imageview = ImageView(self.scene, parent)
        self.img_params = RawImageParams()
        self.img_params = self.load_params(RawImageParams())
        self.img_pipeline = IspPipeline(self.img_params,
                                        process_bar=self.progress_bar)
        self.img = RawImageInfo()
        self.point_data = np.array([0])
        self.scale_ratio = 100
        self.show_img = None
        self.select_awb = False
        self.histView = None

        # 由于graphicsView被自定义了,需要重新定义一下UI,gridlayout还需要重新加一下widget
        self.ui.graphicsView.addWidget(self.imageview, 0, 1, 3, 1)
        self.imageview.sigDragEvent.connect(self.__init_img)
        self.imageview.sigMouseMovePoint.connect(self.show_point_rgb)
        self.imageview.sigWheelEvent.connect(self.update_wheel_ratio)
        # 回调函数初始化
        self.ui.pipeline.doubleClicked.connect(self.update_img_index)
        self.ui.pipeline_ok.clicked.connect(self.update_pipeline)
        self.ui.open_image.clicked.connect(self.open_image)
        self.ui.analysis_img.clicked.connect(self.openHistView)
        self.ui.select_from_raw.clicked.connect(self.select_awb_from_raw)
        self.imageview.rubberBandChanged.connect(self.update_awb_from_raw)
        self.ui.save_image.clicked.connect(self.save_now_image)
        self.ui.reload.clicked.connect(self.img_pipeline.reload_isp)
        self.ui.inputflatphoto.clicked.connect(
            self.img_params.rolloff.set_flatphoto)
        # ISP 处理线程回调
        self.img_pipeline.ispProcthread.doneCB.connect(self.update_img)
        self.img_pipeline.ispProcthread.processRateCB.connect(
            self.update_process_bar)
        self.img_pipeline.ispProcthread.costTimeCB.connect(
            self.update_time_bar)
        self.img_pipeline.ispProcthread.errorCB.connect(self.error_report)
示例#5
0
 def get_image(self, index):
     """
     func: 获取pipeline中的一幅图像
     如果输入-1,则返回最后一幅图像
     """
     ret_img = None
     self.imglist_mutex.acquire()
     if (index < len(self.img_list) and index >= 0):
         ret_img = self.img_list[index]
     elif (index < 0
           and len(self.pipeline) + 1 + index < len(self.img_list)):
         ret_img = self.img_list[len(self.pipeline) + 1 + index]
     self.imglist_mutex.release()
     if (ret_img is not None):
         return ret_img
     else:
         return RawImageInfo()
示例#6
0
def demosaic(raw: RawImageInfo, params: RawImageParams):
    """
    function: demosaic
    input: raw:RawImageInfo() params:RawImageParams()
    demosaic有两种算法,设置demosaic的算法
    0: Malvar-He-Cutler algorithm
    1: directionally weighted gradient based interpolation algorithm
    """
    ret_img = RawImageInfo()
    ret_img.create_image('after demosaic', raw, depth=3)
    if (params.get_demosaic_funct_type() == 0):
        demosaicing_CFA_Bayer_bilinear(raw, ret_img.data)
    elif (params.get_demosaic_funct_type() == 1):
        demosaicing_CFA_Bayer_Malvar2004(raw, ret_img.data)
    elif (params.get_demosaic_funct_type() == 2):
        demosaicing_CFA_Bayer_Menon2007(raw, ret_img.data)
    else:
        return None

    ret_img.clip_range()
    ret_img.set_color_space("RGB")
    return ret_img
示例#7
0
def demosaicing_CFA_Bayer_Malvar2004(raw: RawImageInfo, output):
    """
    *Bayer* CFA (Colour Filter Array) *Malvar (2004)* demosaicing.
    References
    ----------
    -   :cite:`Malvar2004a` : Malvar, H. S., He, L.-W., Cutler, R., & Way, O. M.
        (2004). High-Quality Linear Interpolation for Demosaicing of
        Bayer-Patterned Color Images. International Conference of Acoustic, Speech
        and Signal Processing, 5-8.
        http://research.microsoft.com/apps/pubs/default.aspx?id=102068
    """

    R_m, G_m, B_m = raw.masks_CFA_Bayer()
    CFA = raw.get_raw_data()

    GR_GB = np.float32(
         [[0, 0, -1, 0, 0],
         [0, 0, 2, 0, 0],
         [-1, 2, 4, 2, -1],
         [0, 0, 2, 0, 0],
         [0, 0, -1, 0, 0]]) * 0.125

    Rg_RB_Bg_BR = np.float32(
        [[0, 0, 0.5, 0, 0],
         [0, -1, 0, -1, 0],
         [-1, 4, 5, 4, - 1],
         [0, -1, 0, -1, 0],
         [0, 0, 0.5, 0, 0]]) * 0.125

    Rg_BR_Bg_RB = np.transpose(Rg_RB_Bg_BR)

    Rb_BB_Br_RR = np.float32(
        [[0, 0, -1.5, 0, 0],
         [0, 2, 0, 2, 0],
         [-1.5, 0, 6, 0, -1.5],
         [0, 2, 0, 2, 0],
         [0, 0, -1.5, 0, 0]]) * 0.125

    R = CFA * R_m
    G = CFA * G_m
    B = CFA * B_m

    del G_m

    G = np.where(np.logical_or(R_m == 1, B_m == 1), convolve(CFA, GR_GB), G)

    RBg_RBBR = convolve(CFA, Rg_RB_Bg_BR)
    RBg_BRRB = convolve(CFA, Rg_BR_Bg_RB)
    RBgr_BBRR = convolve(CFA, Rb_BB_Br_RR)

    del GR_GB, Rg_RB_Bg_BR, Rg_BR_Bg_RB, Rb_BB_Br_RR

    # Red rows.
    R_r = np.transpose(np.any(R_m == 1, axis=1)[np.newaxis]) * np.ones(R.shape, dtype=np.float32)
    # Red columns.
    R_c = np.any(R_m == 1, axis=0)[np.newaxis] * np.ones(R.shape, dtype=np.float32)
    # Blue rows.
    B_r = np.transpose(np.any(B_m == 1, axis=1)[np.newaxis]) * np.ones(B.shape, dtype=np.float32)
    # Blue columns
    B_c = np.any(B_m == 1, axis=0)[np.newaxis] * np.ones(B.shape, dtype=np.float32)

    del R_m, B_m

    R = np.where(np.logical_and(R_r == 1, B_c == 1), RBg_RBBR, R)
    R = np.where(np.logical_and(B_r == 1, R_c == 1), RBg_BRRB, R)

    B = np.where(np.logical_and(B_r == 1, R_c == 1), RBg_RBBR, B)
    B = np.where(np.logical_and(R_r == 1, B_c == 1), RBg_BRRB, B)

    R = np.where(np.logical_and(B_r == 1, B_c == 1), RBgr_BBRR, R)
    B = np.where(np.logical_and(R_r == 1, R_c == 1), RBgr_BBRR, B)

    del RBg_RBBR, RBg_BRRB, RBgr_BBRR, R_r, R_c, B_r, B_c

    output[:, :, 2] = R
    output[:, :, 1] = G
    output[:, :, 0] = B
    del R,G,B
    return
示例#8
0
def demosaicing_CFA_Bayer_Menon2007(raw: RawImageInfo, output):
    """
    DDFAPD - Menon (2007) Bayer CFA Demosaicing
    ===========================================
    *Bayer* CFA (Colour Filter Array) DDFAPD - *Menon (2007)* demosaicing.
    References
    ----------
    -   :cite:`Menon2007c` : Menon, D., Andriani, S., & Calvagno, G. (2007).
        Demosaicing With Directional Filtering and a posteriori Decision. IEEE
        Transactions on Image Processing, 16(1), 132-141.
        doi:10.1109/TIP.2006.884928
    """
    R_m, G_m, B_m = raw.masks_CFA_Bayer()
    CFA = raw.get_raw_data()
    h_0 = np.array([0, 0.5, 0, 0.5, 0], dtype=np.float32)
    h_1 = np.array([-0.25, 0, 0.5, 0, -0.25], dtype=np.float32)

    R = CFA * R_m
    G = CFA * G_m
    B = CFA * B_m

    G_H = np.where(G_m == 0, _cnv_h(CFA, h_0) + _cnv_h(CFA, h_1), G)
    G_V = np.where(G_m == 0, _cnv_v(CFA, h_0) + _cnv_v(CFA, h_1), G)

    C_H = np.where(R_m == 1, R - G_H, 0)
    C_H = np.where(B_m == 1, B - G_H, C_H)

    C_V = np.where(R_m == 1, R - G_V, 0)
    C_V = np.where(B_m == 1, B - G_V, C_V)

    D_H = np.abs(C_H - np.pad(C_H, ((0, 0),
                                    (0, 2)), mode=str('reflect'))[:, 2:])
    D_V = np.abs(C_V - np.pad(C_V, ((0, 2),
                                    (0, 0)), mode=str('reflect'))[2:, :])

    del h_0, h_1, CFA, C_V, C_H

    k = np.array(
        [[0, 0, 1, 0, 1],
         [0, 0, 0, 1, 0],
         [0, 0, 3, 0, 3],
         [0, 0, 0, 1, 0],
         [0, 0, 1, 0, 1]], dtype=np.float32)

    d_H = convolve(D_H, k, mode='constant')
    d_V = convolve(D_V, np.transpose(k), mode='constant')

    del D_H, D_V

    mask = d_V >= d_H
    G = np.where(mask, G_H, G_V)
    M = np.where(mask, 1, 0)

    del d_H, d_V, G_H, G_V

    # Red rows.
    R_r = np.transpose(np.any(R_m == 1, axis=1)[np.newaxis]) * np.ones(R.shape, dtype=np.float32)
    # Blue rows.
    B_r = np.transpose(np.any(B_m == 1, axis=1)[np.newaxis]) * np.ones(B.shape, dtype=np.float32)

    k_b = np.array([0.5, 0, 0.5], dtype=np.float32)

    R = np.where(
        np.logical_and(G_m == 1, R_r == 1),
        G + _cnv_h(R, k_b) - _cnv_h(G, k_b),
        R,
    )

    R = np.where(
        np.logical_and(G_m == 1, B_r == 1) == 1,
        G + _cnv_v(R, k_b) - _cnv_v(G, k_b),
        R,
    )

    B = np.where(
        np.logical_and(G_m == 1, B_r == 1),
        G + _cnv_h(B, k_b) - _cnv_h(G, k_b),
        B,
    )

    B = np.where(
        np.logical_and(G_m == 1, R_r == 1) == 1,
        G + _cnv_v(B, k_b) - _cnv_v(G, k_b),
        B,
    )

    R = np.where(
        np.logical_and(B_r == 1, B_m == 1),
        np.where(
            M == 1,
            B + _cnv_h(R, k_b) - _cnv_h(B, k_b),
            B + _cnv_v(R, k_b) - _cnv_v(B, k_b),
        ),
        R,
    )

    B = np.where(
        np.logical_and(R_r == 1, R_m == 1),
        np.where(
            M == 1,
            R + _cnv_h(B, k_b) - _cnv_h(R, k_b),
            R + _cnv_v(B, k_b) - _cnv_v(R, k_b),
        ),
        B,
    )

    del k_b, R_r, B_r

    del M, R_m, G_m, B_m
    output[:, :, 2] = R
    output[:, :, 1] = G
    output[:, :, 0] = B
    del R,G,B
    return
示例#9
0
class RawImageEditor(SubWindow):
    def __init__(self, name='RawImageEditor', parent=None):
        super().__init__(name, parent, Ui_ImageEditor(), need_processBar=True)

        self.scene = QGraphicsScene()
        self.imageview = ImageView(self.scene, parent)
        self.img_params = RawImageParams()
        self.img_params = self.load_params(RawImageParams())
        self.img_pipeline = IspPipeline(self.img_params,
                                        process_bar=self.progress_bar)
        self.img = RawImageInfo()
        self.point_data = np.array([0])
        self.scale_ratio = 100
        self.show_img = None
        self.select_awb = False
        self.histView = None

        # 由于graphicsView被自定义了,需要重新定义一下UI,gridlayout还需要重新加一下widget
        self.ui.graphicsView.addWidget(self.imageview, 0, 1, 3, 1)
        self.imageview.sigDragEvent.connect(self.__init_img)
        self.imageview.sigMouseMovePoint.connect(self.show_point_rgb)
        self.imageview.sigWheelEvent.connect(self.update_wheel_ratio)
        # 回调函数初始化
        self.ui.pipeline.doubleClicked.connect(self.update_img_index)
        self.ui.pipeline_ok.clicked.connect(self.update_pipeline)
        self.ui.open_image.clicked.connect(self.open_image)
        self.ui.analysis_img.clicked.connect(self.openHistView)
        self.ui.select_from_raw.clicked.connect(self.select_awb_from_raw)
        self.imageview.rubberBandChanged.connect(self.update_awb_from_raw)
        self.ui.save_image.clicked.connect(self.save_now_image)
        self.ui.reload.clicked.connect(self.img_pipeline.reload_isp)
        self.ui.inputflatphoto.clicked.connect(
            self.img_params.rolloff.set_flatphoto)
        # ISP 处理线程回调
        self.img_pipeline.ispProcthread.doneCB.connect(self.update_img)
        self.img_pipeline.ispProcthread.processRateCB.connect(
            self.update_process_bar)
        self.img_pipeline.ispProcthread.costTimeCB.connect(
            self.update_time_bar)
        self.img_pipeline.ispProcthread.errorCB.connect(self.error_report)

    def error_report(self, value):
        """
        func: 报告ISP算法错误
        """
        critical(value, self)

    def update_img(self):
        """
        func: ISP 处理完成后的显示回调函数
        """
        self.displayImage(self.img_pipeline.get_image(-1))

    def update_process_bar(self, value):
        """
        func: ISP 处理进度回调
        """
        self.progress_bar.setValue(value)

    def update_time_bar(self, value):
        """
        func:ISP 处理时长回调
        """
        self.time_bar.setText(value)

    def show(self):
        """
        func: 显示初始化
        """
        super().show()
        self.img_params.set_img_params_ui(self.ui)
        self.ui.filename.repaint()
        if (self.img_params.rawformat.filename != ""):
            self.update_pipeline()
            self.img = self.img_pipeline.get_image(-1)
            self.displayImage(self.img)
            self.rect = [
                0, 0, self.img_params.rawformat.width,
                self.img_params.rawformat.height
            ]

    def displayImage(self, img):
        """
        显示图像 输入需要是RawImageInfo
        """
        self.scene.clear()
        self.img = img
        self.show_img = img.get_showimage()
        if (self.show_img is not None):
            showimg = QImage(self.show_img, self.show_img.shape[1],
                             self.show_img.shape[0], QImage.Format_BGR888)
            self.scene.addPixmap(QPixmap(showimg))
            self.ui.photo_title.setTitle(img.get_name())
            if (self.histView is not None and self.histView.enable is True):
                self.histView.update_rect_data(self.show_img, self.rect)

    def select_awb_from_raw(self):
        """
        func: 进入raw图选择模式,修改鼠标类型
        """
        self.imageview.setDragMode(QGraphicsView.RubberBandDrag)
        self.select_awb = True

    def update_awb_from_raw(self, viewportRect, fromScenePoint, toScenePoint):
        """
        func: 鼠标选中事件的回调:执行AWB的选择区域或者图像分析的选择区域
        """
        if (toScenePoint.x() == 0 and toScenePoint.y() == 0
                and self.rect[2] > self.rect[0]
                and self.rect[3] > self.rect[1]):
            if (self.select_awb == True):
                self.imageview.setDragMode(QGraphicsView.ScrollHandDrag)
                self.select_awb = False
                awb_ratio = self.img.get_raw_img_rect(self.rect)
                if (awb_ratio is not None):
                    self.img_params.awb.set_awb_ratio(awb_ratio)
                    awb_gain = self.img_params.awb.get_awb_gain()
                    self.ui.awb_r.setValue(awb_gain[0])
                    self.ui.awb_g.setValue(awb_gain[1])
                    self.ui.awb_b.setValue(awb_gain[2])
                else:
                    critical("请在raw图上进行选择")
            else:
                if (self.histView is not None):
                    self.histView.update_rect_data(self.show_img, self.rect)
        else:
            self.rect = [
                int(fromScenePoint.x()),
                int(fromScenePoint.y()),
                int(toScenePoint.x()),
                int(toScenePoint.y())
            ]

    def update_pipeline(self):
        """
        func: 运行ISP pipeline
        """
        self.img_params.get_img_params(self.ui)
        self.img_pipeline.pipeline_clear()
        for i in range(self.ui.pipeline.count()):
            if (self.ui.pipeline.item(i).checkState() == Qt.Checked):
                self.img_pipeline.add_pipeline_node(
                    self.ui.pipeline.item(i).data(0))
        self.img_pipeline.run_pipeline()

    def update_img_index(self, item):
        """
        func: 更新当前画面的序号
        """
        if (self.ui.pipeline.item(item.row()).checkState() == Qt.Checked):
            index = self.img_pipeline.get_pipeline_node_index(item.data()) + 1
            self.displayImage(self.img_pipeline.get_image(index))

    def open_image(self):
        """
        func: 打开图片的回调函数
        """
        if (self.img_params.rawformat.filename != ''):
            now_path = os.path.dirname(self.img_params.rawformat.filename)
        else:
            now_path = './'
        imagepath = QFileDialog.getOpenFileName(None, '打开RAW图', now_path,
                                                "raw (*.raw)")
        self.__init_img(imagepath[0])

    def __init_img(self, filename):
        if (filename != ''):
            self.ui.filename.setText(filename)
            self.ui.filename.repaint()
            self.update_pipeline()
            self.img = self.img_pipeline.get_image(-1)
            self.rect = [
                0, 0, self.img_params.rawformat.width,
                self.img_params.rawformat.height
            ]

    def save_now_image(self):
        """
        func: 保存图片的回调
        """
        if (self.img.get_raw_data() is not None):
            imagepath = QFileDialog.getSaveFileName(None, '保存图片', './',
                                                    "Images (*.jpg)")
            if (imagepath[0] != ""):
                self.img.save_image(imagepath[0])

    def show_point_rgb(self, point):
        """
        func: 鼠标移动的回调
        """
        self.x = int(point.x())
        self.y = int(point.y())
        if (self.img.get_raw_data() is not None):
            point_data = self.img.get_img_point(self.x, self.y)
            if (point_data is not None):
                self.point_data = point_data
                self.set_img_info_show()

    def update_wheel_ratio(self, ratio):
        """
        func: 鼠标滚轮的回调
        """
        if (self.img.get_raw_data() is not None):
            self.scale_ratio = int(ratio * 100)
            self.set_img_info_show()

    def set_img_info_show(self):
        """
        func: 显示像素点的值以及缩放比例
        """
        if (self.point_data.size == 1):
            self.info_bar.setText("x:{},y:{} : {}: 亮度:{} 缩放比例:{}%".format(
                self.x, self.y,
                self.img.get_img_point_pattern(self.y, self.x).upper(),
                self.point_data, self.scale_ratio))
        elif (self.point_data.size == 3):
            if (self.img.get_color_space() == 'RGB'):
                self.info_bar.setText(
                    "x:{},y:{} : R:{} G:{} B:{} 缩放比例:{}%".format(
                        self.x, self.y, self.point_data[2], self.point_data[1],
                        self.point_data[0], self.scale_ratio))
            else:
                self.info_bar.setText(
                    "x:{},y:{} : Y:{} Cr:{} Cb:{} 缩放比例:{}%".format(
                        self.x, self.y, self.point_data[0], self.point_data[1],
                        self.point_data[2], self.scale_ratio))

    def openHistView(self):
        self.histView = HistView(self.imageview)
        rect = [0, 0, self.show_img.shape[1], self.show_img.shape[0]]
        self.histView.update_rect_data(self.show_img, rect)
        self.histView.show()