ISP shading和 双线性插值代码

ISP shading和 双线性插值代码_第1张图片ISP shading和 双线性插值代码_第2张图片

import math
import os

import numpy as np
import cv2
from colour_demosaicing import demosaicing_CFA_Bayer_bilinear
from matplotlib import pyplot as plt


def black_sub(filename, height=800, width=800):
    raw_image = np.fromfile(filename, dtype=np.uint16)
    print(len(raw_image))
    raw_image = raw_image.reshape([height, width])

    # raw_image =raw_image>>6
    print('raw20x20 :\n', raw_image[20:30, 20:30])
    # black level
    black_level = 16
    white_level = 1023
    normalized_image = raw_image.astype(np.float32) - black_level
    # if some values were smaller than black level
    normalized_image[normalized_image < 0] = 0
    normalized_image = normalized_image / (white_level - black_level)

    print(normalized_image.min(), normalized_image.max())
    # plt.figure()
    # plt.imshow(normalized_image, cmap='gray')
    # plt.show()
    # demosciac
    # rgb = demosaicing_CFA_Bayer_Menon2007(normalized_image, "BGGR")
    rgb = demosaicing_CFA_Bayer_bilinear(normalized_image, "RGGB")
    rgb_save = rgb * 255
    rgb_save = np.clip(rgb_save, 0, 255)
    rgb_save = rgb_save.astype(np.uint8)
    cv2.imwrite(filename[:-4] + '_raw.png', rgb_save[..., ::-1])

    return normalized_image

def bilinear_interp2(data, new_h, new_w):
    """
    与opencv的resize bilinear 函数一致
    :param data:
    :param new_h:
    :param new_w:
    :return:
    """

    h, w = data.shape
    out = np.zeros((new_h, new_w), dtype=np.float32)
    for i in range(new_h):
        for j in range(new_w):
            hv = (i+0.5)*h/new_h-0.5
            wv = (j+0.5)*w/new_w-0.5
            hh = math.floor(hv)
            ww = math.floor(wv)
            u = hv-hh
            v = wv-ww

            if hh < 0:
                hh = 0
                u = 0
            if hh >= h - 1:
                hh = h - 2
                u = 1.0

            if ww < 0:
                ww = 0
                v = 0
            if ww >= w - 1:
                ww = w - 2
                v = 1.0

                #print(hh, ww)
            out[i, j] = (1-u)*(1-v)*data[hh, ww]+u*(1-v)*data[hh+1, ww]+(1-u)*v*data[hh, ww+1]+u*v*data[hh+1, ww+1]
    return out

def bilinear_interp1(data, new_h, new_w):

    h, w = data.shape
    out = np.zeros((new_h, new_w), dtype=np.float32)

    # u_save = []
    for i in range(new_h):
        for j in range(new_w):
            hv = (i+0.5)*(h-1)/(new_h-1)-0.5
            wv = (j+0.5)*(w-1)/(new_w-1)-0.5
            hh = math.floor(hv)
            ww = math.floor(wv)
            u = hv-hh
            v = wv-ww
            #print(hh, ww)
            # u_save.append(u)
            out[i, j] = (1-u)*(1-v)*data[hh, ww]+u*(1-v)*data[hh+1, ww]+(1-u)*v*data[hh, ww+1]+u*v*data[hh+1, ww+1]
    # u_save = np.array(u_save)
    # np.savetxt('u1.txt', u_save.reshape([new_h, new_w]))
    return out


def bilinear_interp(data, new_h, new_w):
    """
    :param data: origin data
    :param new_h: the height of dst
    :param new_w: the width of dst
    :return:
    """
    h, w = data.shape   # the height and width of origin data
    y = np.arange(new_h)
    x = np.arange(new_w)
    jj, ii = np.meshgrid(x, y)

    hv = (ii + 0.5) * (h - 1) / (new_h - 1) - 0.5
    wv = (jj + 0.5) * (w - 1) / (new_w - 1) - 0.5

    hh = np.floor(hv).astype(np.int32)
    ww = np.floor(wv).astype(np.int32)
    u = hv - hh
    v = wv - ww
    # np.savetxt('u0.txt', u.reshape([new_h, new_w]))
    # data = data.reshape(-1)
    # hh = hh.reshape(-1).astype(np.int)
    # ww = hh.reshape(-1).astype(np.int)
    # u = u.reshape(-1)
    # v = v.reshape(-1)

    w00 = (1-u)*(1-v)
    w01 = u * (1-v)
    w10 = (1-u) * v
    w11 = u*v
    out = w00 * data[hh, ww] + w10 * data[hh, ww + 1] + w01 * data[(hh + 1) ,ww] + w11 * data[hh + 1 , ww + 1]


    # out= (1 - u) * (1 - v) * data[hh, ww] + u * (1 - v) * data[hh + 1, ww] + (1 - u) * v * data[
    #     hh, ww + 1] + u * v * data[hh + 1, ww + 1]
    return out.reshape([new_h, new_w])

def bilinear_interp3(data, new_h, new_w):
    """
    :param data: origin data
    :param new_h: the height of dst
    :param new_w: the width of dst
    :return:
    """
    h, w = data.shape   # the height and width of origin data
    y = np.arange(new_h)
    x = np.arange(new_w)
    jj, ii = np.meshgrid(x, y)

    hv = (ii + 0.5) * h/new_h - 0.5
    wv = (jj + 0.5) * w/new_w - 0.5

    hh = np.floor(hv).astype(np.int32)
    ww = np.floor(wv).astype(np.int32)
    u = hv - hh
    v = wv - ww


    u[hh < 0] = 0
    hh[hh < 0] = 0
    u[hh >= h - 1] = 1.0
    hh[hh >= h - 1] = h - 2

    v[ww < 0] = 0
    ww[ww < 0] = 0
    v[ww >= w - 1] = 1.0
    ww[ww >= w - 1] = w - 2

    # np.savetxt('u0.txt', u.reshape([new_h, new_w]))
    # data = data.reshape(-1)
    # hh = hh.reshape(-1).astype(np.int)
    # ww = hh.reshape(-1).astype(np.int)
    # u = u.reshape(-1)
    # v = v.reshape(-1)

    w00 = (1-u)*(1-v)
    w01 = u * (1-v)
    w10 = (1-u) * v
    w11 = u*v
    out = w00 * data[hh, ww] + w10 * data[hh, ww + 1] + w01 * data[(hh + 1) ,ww] + w11 * data[hh + 1 , ww + 1]
    # fpga中可以通过查找表来实现
    # 在初始尺寸以及目标尺寸确定之后(h,w,new_h,new_w), w00,w01,w10,w11这四个变量对于任何图像都是一致的和确定的。
    # hh, ww对于任何图像也是一致的和确定的
    # 因此首先保存下来,然后通过查找来实现


    return out.reshape([new_h, new_w])






if __name__ == "__main__":

    interpolation = 'bilinear'  # cubic, area, nearest
    table_h = 40
    table_w = 40
    if interpolation == 'bilinear':
        inter = cv2.INTER_LINEAR
    elif interpolation == 'nearest':
        inter = cv2.INTER_NEAREST
    elif interpolation == 'cubic':
        inter = cv2.INTER_CUBIC
    elif interpolation == 'area':
        inter = cv2.INTER_AREA
    else:
        print('error input !')
    height = 800
    width = 800
    new_h = 400
    new_w = 400

    dir = r'D:\code\interp\image'
    files = os.listdir(dir)
    for file in files:
        if file.endswith('.raw'):
            filename = os.path.join(dir, file)
            normalized_image = black_sub(filename)

            run_pipe_shading = 1
            if run_pipe_shading:
                # shading
                # r_gain = np.loadtxt(r'D:\dataset\calib\shading\gains_mean_r.txt', dtype=np.float32)
                # g_gain = np.loadtxt(r'D:\dataset\calib\shading\gains_mean_g.txt', dtype=np.float32)
                # b_gain = np.loadtxt(r'D:\dataset\calib\shading\gains_mean_b.txt', dtype=np.float32)

                r_gain = np.loadtxt(r'D:\code\interp\gains_mean_r.txt', dtype=np.float32)
                g_gain = np.loadtxt(r'D:\code\interp\gains_mean_g.txt', dtype=np.float32)
                b_gain = np.loadtxt(r'D:\code\interp\gains_mean_b.txt', dtype=np.float32)
                # valid_table

                r_gain = cv2.resize(r_gain, (table_h, table_w), interpolation=cv2.INTER_LINEAR)
                g_gain = cv2.resize(g_gain, (table_h, table_w), interpolation=cv2.INTER_LINEAR)
                b_gain = cv2.resize(b_gain, (table_h, table_w), interpolation=cv2.INTER_LINEAR)

                np.savetxt(r'D:\code\interp\gains_mean_r' + interpolation + str(table_w) + '.txt', r_gain, fmt='%.7f')
                np.savetxt(r'D:\code\interp\gains_mean_g' + interpolation + str(table_w) + '.txt', g_gain, fmt='%.7f')
                np.savetxt(r'D:\code\interp\gains_mean_b' + interpolation + str(table_w) + '.txt', b_gain, fmt='%.7f')

                # r_gain = cv2.resize(r_gain, (height // 2, width // 2), interpolation=inter)
                # g_gain = cv2.resize(g_gain, (height // 2, width // 2), interpolation=inter)
                # b_gain = cv2.resize(b_gain, (height // 2, width // 2), interpolation=inter)

                r_gain = bilinear_interp3(r_gain, new_h, new_w)
                g_gain = bilinear_interp3(g_gain, new_h, new_w)
                b_gain = bilinear_interp3(b_gain, new_h, new_w)

                normalized_image[0::2, 0::2] *= r_gain
                normalized_image[1::2, 1::2] *= g_gain
                normalized_image[0::2, 1::2] *= g_gain
                normalized_image[1::2, 0::2] *= b_gain

                rgb = demosaicing_CFA_Bayer_bilinear(normalized_image, "RGGB")
                # brigtness_aline = 1
                # if brigtness_aline:
                #     rgb *= 2.7

                rgb_save = rgb * 255
                rgb_save = np.clip(rgb_save, 0, 255)
                rgb_save = rgb_save.astype(np.uint8)
                cv2.imwrite(filename[:-4] + 'z3_raw_shading_' + interpolation + str(table_w) + '.png',
                            rgb_save[..., ::-1])

  1. c++版本code , 和opencv resize基本一致,因为有数据转换,所以有精度损失
    https://blog.csdn.net/hddryjv/article/details/83791042?spm=1001.2101.3001.6650.1&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-1-83791042-blog-106761993.pc_relevant_default&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-1-83791042-blog-106761993.pc_relevant_default&utm_relevant_index=2
    OpenCV中resize函数五种插值算法的实现过程
#include 
#include 

using namespace cv;
//typedef unsigned char uchar;


int bilinear_interp(Mat matSrc, Mat matDst1, Mat matDst2, float scale_x, float scale_y) {
    uchar* dataDst = matDst1.data; 
    int stepDst = matDst1.step; 
    uchar* dataSrc = matSrc.data; 
    int stepSrc = matSrc.step; 
    int iWidthSrc = matSrc.cols; 
    int iHiehgtSrc = matSrc.rows; 

    for (int j = 0; j < matDst1.rows; ++j) 
    { 
        float fy = (float)((j + 0.5) * scale_y - 0.5);  
        int sy = cvFloor(fy);  
        fy -= sy;  
        //sy = std::min(sy, iHiehgtSrc - 2);  
        //sy = std::max(0, sy);
        
        if (sy < 0)
        {
            fy = 0, sy = 0;
        }
        if (sy >= iHiehgtSrc - 1)
        {
            fy = 1.0, sy = iHiehgtSrc - 2;
        }
        

        short cbufy[2];  
        cbufy[0] = cv::saturate_cast((1.f - fy) * 2048);  
        cbufy[1] = 2048 - cbufy[0];  
        for (int i = 0; i < matDst1.cols; ++i) 
        {
            float fx = (float)((i + 0.5) * scale_x - 0.5);   
            int sx = cvFloor(fx);   
            fx -= sx;   
            
            if (sx < 0) 
            { 
                fx = 0, sx = 0; 
            }   
            if (sx >= iWidthSrc - 1) 
            { 
                fx = 1.0, sx = iWidthSrc - 2; 
            }   
            
            short cbufx[2];   
            cbufx[0] = cv::saturate_cast((1.f - fx) * 2048);   
            cbufx[1] = 2048 - cbufx[0];

            for (int k = 0; k < matSrc.channels(); ++k) 
            { 
                *(dataDst + j * stepDst + 3 * i + k) = (*(dataSrc + sy * stepSrc + 3 * sx + k) * cbufx[0] * cbufy[0] + 
                                                        *(dataSrc + (sy + 1) * stepSrc + 3 * sx + k) * cbufx[0] * cbufy[1] + 
                                                        *(dataSrc + sy * stepSrc + 3 * (sx + 1) + k) * cbufx[1] * cbufy[0] + 
                                                        *(dataSrc + (sy + 1) * stepSrc + 3 * (sx + 1) + k) * cbufx[1] * cbufy[1]) >> 22;
            } 
        } 
    } 
    cv::imwrite("linear_12.jpg", matDst1); 
    
    cv::resize(matSrc, matDst2, matDst1.size(), 0, 0, 1); 
    cv::imwrite("linear_2.jpg", matDst2);
    return 1;
}
int main()
{
    std::cout << "Hello World!\n";

    Mat img;  //
    img = imread("D:\\dataset\\\ccm\\2022-06-21-15-08-20_raw_gamma3.png");
    int width = img.cols;
    int height = img.rows;

    if (img.empty())  // 判断是否导入图片
    {
        std::cout << "请确认图片正确位置!" << std::endl;
        return -1;  // 返回-1
    }
    namedWindow("test", WINDOW_NORMAL);  // 创建一个常规窗口

    imshow("test", img);  // 展示图片
    waitKey(0);  // 获取键盘按键响应


    int dstHeight = height * 2;
    int dstWidth = width * 2;

    Mat img2(dstHeight, dstWidth, CV_8UC3), img3(dstHeight, dstWidth, CV_8UC3);
   

    float scale_x = 0.5;
    float scale_y = 0.5;
    bilinear_interp(img, img2, img3, scale_x, scale_y);
        
}

你可能感兴趣的:(图像处理算法,python,numpy,计算机视觉)