Python-Opencv 图像操作大合集

1. 空域图像操作

在空间域对图像可以进行加噪声(椒盐噪声,高斯噪声),对比度增强(直方图均衡化),平滑滤波,锐化

1.1. 加噪声

首先是椒盐噪声,究其原理,其实就是随机在图像上将一些点设置为纯白色(盐)或者纯黑色(椒),那么我们只要知道需要加的个数,就可以通过生成随机数的方式加噪声。

def sp_noise(img, prob, is_gray = False):
    image = np.array(img)
    height = img.shape[0]
    width = img.shape[1]
    image_noise = image.copy()
    # 得到需要增加噪声的个数
    num_noise = int(prob * height * width)
    for i in range(num_noise):
        # 随机生成当前噪声的坐标
        rows = np.random.randint(0, height - 1)
        cols = np.random.randint(0, width - 1)
        if is_gray: # 灰度图只需要在当前位置置为0/255
            if np.random.randint(0, 2) == 0:
                image_noise[rows, cols] = 0
            else:
                image_noise[rows, cols] = 255
        else: # RGB彩色图,需要在三个通道都置为0/255
            if np.random.randint(0, 2) == 0:
                image_noise[rows, cols, :] = 0
            else:
                image_noise[rows, cols, :] = 255
            
    return image_noise                  

原图:

Python-Opencv 图像操作大合集_第1张图片

 加入椒盐噪声(prob=0.1):

Python-Opencv 图像操作大合集_第2张图片

第二种是高斯噪声,这个的原理是产生指定均值和方差的高斯噪声值,然后直接加在全图上,由于可能有超过[0,255]范围的值,最后再进行修正就行。

def gasuss_noise(img, mean=0, std=0.01):
    img = np.array(img / 255, dtype=float)
    # 产生高斯随机值
    noise = np.random.normal(mean, std ** 0.5, img.shape)
    out = img + noise
    # 修正
    if out.min() < 0:
        low_clip = -1.
    else:
        low_clip = 0.
    out = np.clip(out, low_clip, 1.0)
    out = np.round(out * 255).astype(np.uint8)
    return out

 加入高斯噪声(mean=0, std=0.01):

Python-Opencv 图像操作大合集_第3张图片

 

1.2. 直方图均衡化

由于有些图片偏亮或者偏暗,通道的像素值会集中于某个区域,所以将其展开平均到整个区域内,会得到类似对比度增强的效果。

对于灰度图像,直接调用cv2.equalizeHist(image)即可,多通道的图片需要对每个通道进行操作然后合并

def equalizeHist_rgb(img):
    # 通道分离
    r, g, b = cv2.split(img)
    r_hist = cv2.equalizeHist(r)
    g_hist = cv2.equalizeHist(g)
    b_hist = cv2.equalizeHist(b)
    # 通道合并
    equal_out = cv2.merge((r_hist, g_hist, b_hist))
    return equal_out

 处理后效果:
Python-Opencv 图像操作大合集_第4张图片

 图像和原图对比远处森林和近处倒影都清晰了不少

1.3. 平滑滤波、锐化处理

在空域中的滤波操作,其实就是采用不同算子的卷积操作

常用平滑滤波器(低通滤波器):

平均模板:

Python-Opencv 图像操作大合集_第5张图片

中心加权模板:

Python-Opencv 图像操作大合集_第6张图片

 高斯模板:

Python-Opencv 图像操作大合集_第7张图片

 常用锐化模板:

Python-Opencv 图像操作大合集_第8张图片

def sharp(img):
    kernel = np.array([[0, -1, 0], [-1, 5, -1], [0, -1, 0]], np.float32)
    img_sharp = cv2.filter2D(img, -1, kernel=kernel)
    return img_sharp

def smooth(img):
    kernel = np.array([[1, 1, 1], [1, 1, 1], [1, 1, 1]], np.float32)
    img_smooth = cv2.filter2D(img, -1, kernel=kernel)
    return img_smooth

 平滑处理结果(11*11高斯低通核):

Python-Opencv 图像操作大合集_第9张图片

 锐化处理结果(3*3高斯高通核)

Python-Opencv 图像操作大合集_第10张图片

 2. 频域图像操作

空域到频域的变化是傅里叶变换,于是在空域中的卷积操作就等于在频域中的乘积

2.1. 平滑

由于理想低通滤波器傅里叶变换之后会产生振铃现象,产生不必要的噪声,所以我们采用高斯滤波器

高斯低通滤波器函数:

 首先,由于图像直接傅里叶变换之后低频部分在四个角落,所以我们要先变换到中间,而在处理之后还需要还原

傅里叶预处理函数:

def stdFftImage(img_gray, rows, cols):
    fimg = np.copy(img_gray)
    fimg = fimg.astype(np.float32)
    # 中心化
    for r in range(rows):
        for c in range(cols):
            if (r+c) % 2:
                fimg[r][c] = -1 * img_gray[r][c]
    img_fft = fftImage(fimg, rows, cols)
    return img_fft

def fftImage(img_gray, rows, cols):
    rPadded = cv2.getOptimalDFTSize(rows)
    cPadded = cv2.getOptimalDFTSize(cols)
    imgPadded = np.zeros((rPadded, cPadded), dtype=np.float32)
    imgPadded[:rows, :cols] = img_gray
    img_fft = cv2.dft(imgPadded, flags=cv2.DFT_COMPLEX_OUTPUT)
    return img_fft

def graySpectrum(fft_img):
    real = np.power(fft_img[:, :, 0], 2.0)
    imaginary = np.power(fft_img[:, :, 1], 2.0)
    amplitude = np.sqrt(real+imaginary)
    spectrum = np.log(amplitude+1.0)
    spectrum = cv2.normalize(spectrum, 0, 1, norm_type=cv2.NORM_MINMAX, dtype=cv2.CV_32F)
    spectrum *= 255
    return amplitude, spectrum

平滑处理:

def createLPFilter(shape, center, radius, n=2):
    rows, cols = shape[:2]
    r, c = np.mgrid[0:rows:1, 0:cols:1]
    c -= center[0]
    r -= center[1]
    d = np.power(c, 2.0) + np.power(r, 2.0)
    lpFilter_matrix = np.zeros(shape, np.float32)
    # 低通高斯函数
    lpFilter = np.exp(-d/(2*pow(radius, 2.0)))
    lpFilter_matrix[:, :, 0] = lpFilter
    lpFilter_matrix[:, :, 1] = lpFilter
    return lpFilter_matrix

def smooth_fft(img, radius=100):
    rows, cols = img_gray.shape[:2]
    img_fft = stdFftImage(img_gray, rows, cols)
    amplitude, _ = graySpectrum(img_fft)
    minValue, maxValue, minLoc, maxLoc = cv2.minMaxLoc(amplitude)  
    
    max_radius = np.sqrt(pow(rows, 2) + pow(cols, 2))
    
    nrows, ncols = img_fft.shape[:2]
    # 构建低通高斯函数
    ilpFilter = createHPFilter(img_fft.shape, maxLoc, radius)
    # 频域相乘
    img_filter = ilpFilter * img_fft
    # 图像逆变换
    img_ift = cv2.dft(img_filter, flags=cv2.DFT_INVERSE + cv2.DFT_REAL_OUTPUT + cv2.DFT_SCALE)
    out_img = np.copy(img_ift[:rows, :cols])
    for r in range(rows):
        for c in range(cols):
            if (r + c) % 2:
                out_img[r][c] = -1 * out_img[r][c]
    # 数值溢出修正
    out_img[out_img < 0] = 0
    out_img[out_img > 255] = 255
    out_img = out_img.astype(np.uint8)
    out_img += img
    
    return out_img

以上函数适用于单通道图像,类似地,我们在使用三通道图像的时候需要三个通道分别处理:

def smooth_fft_rgb(img, radius=100):
    img_r, img_g, img_b = cv2.split(img)
    img_r_sharp = smooth_fft(img_r)
    img_g_sharp = smooth_fft(img_g)
    img_b_sharp = smooth_fft(img_b)
    out_img = cv2.merge((img_r, img_g, img_b))
   
    return out_img

 平滑处理效果(radius=100):
Python-Opencv 图像操作大合集_第11张图片

2.2. 锐化处理

与平滑处理唯一不同的就是滤波函数变成了高通函数,而在频域中表现高通函数就是1-低通函数

而纯粹的高通滤波出来的是图像的轮廓信息,加上原图信息就是锐化后的图像

def sharp_fft(img, radius=100):
    rows, cols = img_gray.shape[:2]
    img_fft = stdFftImage(img_gray, rows, cols)
    amplitude, _ = graySpectrum(img_fft)
    minValue, maxValue, minLoc, maxLoc = cv2.minMaxLoc(amplitude)  
    
    max_radius = np.sqrt(pow(rows, 2) + pow(cols, 2))
    
    nrows, ncols = img_fft.shape[:2]
    ilpFilter = createHPFilter(img_fft.shape, maxLoc, radius)

    img_filter = ilpFilter * img_fft

    img_ift = cv2.dft(img_filter, flags=cv2.DFT_INVERSE + cv2.DFT_REAL_OUTPUT + cv2.DFT_SCALE)
    out_img = np.copy(img_ift[:rows, :cols])
    for r in range(rows):
        for c in range(cols):
            if (r + c) % 2:
                out_img[r][c] = -1 * out_img[r][c]
    out_img[out_img < 0] = 0
    out_img[out_img > 255] = 255
    out_img = out_img.astype(np.uint8)
    out_img += img
    
    return out_img

def sharp_fft_rgb(img, radius=100):
    img_r, img_g, img_b = cv2.split(img)
    img_r_sharp = sharp_fft(img_r)
    img_g_sharp = sharp_fft(img_g)
    img_b_sharp = sharp_fft(img_b)
    out_img = cv2.merge((img_r, img_g, img_b))
   
    return out_img

 锐化处理效果(radius=100):

Python-Opencv 图像操作大合集_第12张图片

3. 参考博文

(十)OpenCV-Python学习—频率域滤波 - silence_cho - 博客园

你可能感兴趣的:(图像处理与模式识别,python,图像处理,opencv)