图像处理(一)图像增强:线性灰度变换,直方图均衡化,中值滤波(加/去椒盐噪声)

原理

线性灰度变换

图像反转

灰度线性变换最常见的就是图像反转,在灰度图像灰度级范围[0,L-1]中,其反转的公式如下所示:
在这里插入图片描述
其中,r表示原始图像的灰度级,s表示变换后的灰度级。
低灰度部分经过灰度反转可以得到扩展,看到更多的细节。所以对数变换对照度不均图像中低灰度部分的细节增强很实用。

分段线性灰度变换

分段线性灰度变换能将感兴趣的灰度范围线性扩展,相对抑制不感兴趣的灰度区域。
设f(x,y)灰度范围为[0,Mf],g(x,y)灰度范围为[0,Mg]。如下图所示的变换函数的运算结果是将原图在a到b之间的灰度拉伸到c到d之间。如果一幅图像的灰度集中在较暗的区域而导致图像偏暗,可以用灰度拉伸功能来拉伸(斜率>1)物体灰度区间以改善图像;同样如果图像灰度集中在较亮的区域而导致图像偏亮,也可以用灰度拉伸功能来压缩(斜率<1)物体灰度区间以改善图像质量。
在这里插入图片描述

直方图均衡化

中值滤波

代码

三个方法单独处理

main函数:

from functions import *

def stretch():
    path1 = 'Brain_CT.jpg'
    image1 = image_inten(path1,256)
    image1.show('Oringinal image')
    image1.get_bar()
    image1.stretch(100,0,200,255)
    image1.show('After stretching')
    image1.get_bar()


def equalization():
    path2 = 'Brain_CT.jpg'
    image2 = image_inten(path2,256)
    image2.show('Original image')
    image2.get_bar()
    image2.equalize()
    image2.show('After equalization')
    image2.get_bar()


def remove_noise():
    path3  = 'Brain_CT.jpg'
    # type of noise
    noise_mode = 's&p'
    # linear filter

    filter = np.ones([5,5])
    # filter = [[1,2,1],[2,4,2],[1,2,1]]  set the filter by yourself
    image3 = image_inten(path3,256)
    image3.show('Original image')
    image3.get_bar("Original image")
    # add noise
    # image3.add_noise(noise_mode)
    image3.show('Image with {} noise'.format(noise_mode))

    # filter
    filter = np.array(filter)
    # gaussian noise: image3.filt(filter)
    # s&p noise :
    image3.medium_filter(3)
    image3.show('After filtering')


if __name__ == '__main__':
    # remove_noise()
    stretch()
    equalization()
    remove_noise()

functions:

import numpy as np
import skimage
from skimage import io,data,color
import matplotlib.pyplot as plt
import os
import copy

'''    image intensification   '''
class image_inten():
    def __init__(self,img_path,L):
        self.img_path = img_path
        self.img = io.imread(self.img_path)  # 带一个参数,表示需要读取的文件路径。读取的图片以numpy数组形式计算。
    # Get the grayscale L
        self.L = L  # 白色为255 ,黑色为0,故黑白图片也称灰度图像
    # create the histogram
        self.bar = np.zeros(self.L)
    # get the size of the input image
        self.size = self.img.shape
        self.num_pixels = self.size[0] * self.size[1]
        # self.max_value = np.max(self.img) ?
        # self.min_value = np.max(self.img) ?
    # Convert the RGB image to gray image
        if len(self.size)!=2:
            self.img = color.rgb2gray(self.img)
            self.img = skimage.img_as_ubyte(self.img)
            self.size = self.img.shape
        self.original_img = copy.deepcopy(self.img)

    def show(self,title=''):
        plt.imshow(self.img,plt.cm.gray)  # 画黑白图,如果默认就会画成RGB
        plt.title(title)
        plt.show()

    # Obtain gray statistical histogram
    def get_bar(self,title = ''):
        self.bar = np.zeros(self.L)
        image = copy.deepcopy(self.img)
        img = image.reshape(self.num_pixels)

        for pixel in img:
            self.bar[pixel] +=1
        x = np.arange(self.L)

        plt.bar(x,self.bar)
        plt.title(title)
        plt.show()
        return self.bar

    # gray stretch
    def stretch(self,r1,s1,r2,s2):
        assert(r1<=r2<self.L and s1<=s2<self.L)
        if r1 == r2:
            # r1 == r2 && s1 == s2  nothing changes
            if s1 == s2:
                return
            # s1 != s2  threshold processing
            else:
                self.img[self.img<=r1] = s1
                self.img[self.img>r1] = s2
        else:
            k1 = s1/r1
            k2 = (s2-s1)/(r2-r1)
            k3 = (self.L-1-s2)/(self.L-1-r2)
            b1 = 0
            b2 = s2 - k2*r2
            b3 = s2 - k3*r2

            for i in range(self.size[0]):
                for j in range(self.size[1]):
                    if self.img[i,j]<r1:
                        self.img[i,j] = self.img[i,j]*k1 + b1
                    elif r1 <= self.img[i,j] <r2:
                        self.img[i,j] = self.img[i,j]*k2 + b2
                    else:
                        self.img[i,j] = self.img[i,j]*k3 + b3

    # histogram equalization
    def equalize(self):
        bar = copy.deepcopy(self.bar)
        # sk = T(rk)
        for i in range(self.L):
            sum =0
            for j in range(i):
                sum += bar[j]
            self.bar[i] = int(((self.L-1)/self.num_pixels)*sum + 0.5)
        for i in range(self.size[0]):
            for j in range(self.size[1]):
                self.img[i,j] = self.bar[self.img[i,j]]

    # add noise to the image
    def add_noise(self,noise_mode='gaussian'):
        self.img = skimage.util.random_noise(self.img,mode=noise_mode)

    def filt(self,filter):
        if not isinstance(filter,np.ndarray):
            filter = np.array(filter)
        filter_size = filter.shape
        # the filter should have dimension 2
        assert(len(filter_size) == 2)
        # calculate the padding number
        padding = filter_size[0]//2
        larger_image = np.zeros([self.size[0]+2*padding,self.size[1]+2*padding])
        # pad the image with 0
        larger_image[padding:larger_image.shape[0]-padding,padding:larger_image.shape[1]-padding] = copy.deepcopy(self.img)
        # convolution
        for i in range(self.size[0]):
            for j in range(self.size[1]):

                self.img[i,j] = np.sum(larger_image[i:i+filter_size[0],j:j+filter_size[1]] * filter)
                self.img[i,j] = self.img[i,j]/np.sum(filter)

    # median filter
    def medium_filter(self,filter_size):
        padding = filter_size
        larger_image = np.zeros([self.size[0]+2*padding,self.size[1]+2*padding])
        larger_image[padding:larger_image.shape[0] - padding, padding:larger_image.shape[1] - padding] = copy.deepcopy(
            self.img)
        for i in range(self.size[0]):
            for j in range(self.size[1]):
                # sort and choose the middle number
                self.img[i,j] = np.sort(larger_image[i:i+filter_size,j:j+filter_size].reshape(filter_size**2))[(filter_size**2)//2]

线性灰度变换的参数调试程序

在下图的参数中具体调节了三个参数的值,分别是a,b,和d-c。设a为x1,b为x2,(d-c)为y,取Mg和Mf均为256,x1在100到150之间每隔10取一次值,x2在150到190之间每隔10取一次值,y在180到230之间每隔10取一次值。
在这里插入图片描述

import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt

def gray_trans(img, x1 ,x2 ,y):

    temp = img
    rows = temp.shape[0]
    cols = temp.shape[1]
    for i in range(rows):
        for j in range(cols):
            if temp[i][j] < x1:
                temp[i][j] = (256-y)*temp[i][j]/(256-x2+x1)
            elif temp[i][j] >= x1 and temp[i][j] <= x2:
                temp[i][j] = (256-y)*x1/(256-x2+x1)+y/(x2-x1)*(temp[i][j]-x1)
            elif temp[i][j] > x2:
                temp[i][j] = (256-y)*(temp[i][j]-x2+x1)/(256-x2+x1)+y
    
    return temp


for i in range(100, 150, 10):
    for j in range(150, 190, 10):
        for k in range(180, 230, 10):
            path = './Brain_CT.jpg'
            img = cv.imread(path, 0)
            gam_img = gray_trans(img, i, j, k)
            cv.imshow('GrayTrans Image x1:'+str(i)+'x2:'+str(j)+'y'+str(k), gam_img)
            cv.waitKey(0)
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值