数字图像处理期中作业

1、图像分块后对每一个分块进行直方图均衡化,获取增强结果
2、对局部增强前后图像利用prewitt算子计算边缘
3、对边缘图像按照图像均值进行二值化
4、对二值化以后的图像提取轮廓
在这里插入图片描述

图像的分块

 m, n = img.shape
    img1 = img[:int(m / 2), :int(n / 2)]
    img2 = img[:int(m / 2), int(n / 2):]
    img3 = img[int(m / 2):, :int(n / 2)]
    img4 = img[int(m / 2):, int(n / 2):]

均衡化

# 绘制直方图
def histogram(img):
    # 判断数据类型
    if img.dtype == 'uint8':
        hist = np.zeros(256)
        l = 256
    elif img.dtype == 'uint16':
        hist = np.zeros(65536)
        l = 65536
    else:
        return 0
    for i in range(img.shape[0]):
        for j in range(img.shape[1]):
            hist[img[i][j]] += 1
    return l, hist


# 直方图均衡化
def level(img):
    # 绘制直方图
    L, hist = histogram(img)
    # 建一个空数组
    Cumulative_histogram = {}
    tmp = 0
    for i in range(hist.size):
        if hist[i] != 0:
            Cumulative_histogram[i] = hist[i] / img.size + tmp
            tmp = Cumulative_histogram[i]

    for i in Cumulative_histogram.keys():
        tmp = math.floor((L - 1) * Cumulative_histogram[i] + 0.5)
        Cumulative_histogram[i] = tmp

    new_img = np.array(img)
    for i in range(img.shape[0]):
        for j in range(img.shape[1]):
            if img[i][j] in Cumulative_histogram.keys():
                new_img[i][j] = Cumulative_histogram[img[i][j]]

    return new_img

获取局部增强结果

# 分块直方图均衡化,获取局部增强结果
def devide(img):
    # 图像分块
    m, n = img.shape
    img1 = img[:int(m / 2), :int(n / 2)]
    img2 = img[:int(m / 2), int(n / 2):]
    img3 = img[int(m / 2):, :int(n / 2)]
    img4 = img[int(m / 2):, int(n / 2):]

    # 对分块后的直方图均衡化
    '''
    方法一
    ret1 = cv2.equalizeHist(img1)
    ret2 = cv2.equalizeHist(img2)
    ret3 = cv2.equalizeHist(img3)
    ret4 = cv2.equalizeHist(img4)
    '''

    # 方法二
    ret1 = level(img1)
    ret2 = level(img2)
    ret3 = level(img3)
    ret4 = level(img4)

    # 合并图像
    level1_img = np.zeros(img.shape)
    level1_img[:math.ceil(m / 2), :math.ceil(n / 2)] = ret1
    level1_img[:math.ceil(m / 2), math.ceil(n / 2):] = ret2
    level1_img[math.ceil(m / 2):, :math.ceil(n / 2)] = ret3
    level1_img[math.ceil(m / 2):, math.ceil(n / 2):] = ret4
    return level1_img

利用prewitt进行边缘锐化

# 卷积
def imgConvolve(image, kernel):
    '''
    :param image: 图片矩阵
    :param kernel: 滤波窗口
    :return:卷积后的矩阵
    '''

    img_h, img_w = image.shape
    kernel_h, kernel_w = kernel.shape
    # padding
    padding_h = int((kernel_h - 1) / 2)
    padding_w = int((kernel_w - 1) / 2)

    convolve_h = int(img_h + 2 * padding_h)
    convolve_W = int(img_w + 2 * padding_w)

    # 分配空间
    img_padding = np.zeros((convolve_h, convolve_W))
    # 中心填充图片
    img_padding[padding_h:padding_h + img_h, padding_w:padding_w + img_w] = image[:, :]
    # 卷积结果
    image_convolve = np.zeros(image.shape)
    # 卷积
    for i in range(padding_h, padding_h + img_h):
        for j in range(padding_w, padding_w + img_w):
            image_convolve[i - padding_h][j - padding_w] = int(
                np.sum(img_padding[i - padding_h:i + padding_h + 1, j - padding_w:j + padding_w + 1] * kernel))

    return image_convolve


# Prewitt算子边缘锐化
def prewittEdge(image, prewitt_x, prewitt_y):
    '''
    :param image: 图片矩阵
    :param prewitt_x: 竖直方向
    :param prewitt_y: 水平方向
    :return:处理后的矩阵
    '''
    img_X = imgConvolve(image, prewitt_x)
    img_Y = imgConvolve(image, prewitt_y)

    img_prediction = np.zeros(img_X.shape)
    for i in range(img_prediction.shape[0]):
        for j in range(img_prediction.shape[1]):
            img_prediction[i][j] = max(img_X[i][j], img_Y[i][j])
    return img_prediction

对边缘图像均匀二值化

# 图像二值化
def custom_threshold(image):
    # 计算图像均值
    h, w = image.shape[:2]
    m = np.reshape(image, [1, w * h])
    mean = m.sum() / (w * h)
    # 给定参数二值化
    ret, binary = cv2.threshold(image, mean, 255, cv2.THRESH_BINARY)
    return binary

对二值化以后图像提取轮廓

# 轮廓拟合
def contours_demo(image):
    # 原始二值化得到的图像是float类型,进行类型转换
    image = np.array(image, dtype='uint8')
    """
        cloneimage 显示图像,查找轮廓
        需要注意的是此处是cv2版本
        cv在2和4版本里面cv2.findContours需要的是两个参数
        在3版本里面只需要两个参数改成
        contours, heriachy = cv2.findContours(image, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
        即可
    """
    cloneimage, contours, heriachy = cv2.findContours(image, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
    # 绘制图像
    for i, contour in enumerate(contours):
        """
            函数cv2.drawContours()被用来绘制轮廓。
            第一个参数是一张图片,可以是原图或者其他。
            第二个参数是轮廓,也可以说是cv2.findContours()找出来的点集,一个列表。
            第三个参数是对轮廓(第二个参数)的索引,当需要绘制独立轮廓时很有用,若要全部绘制可设为-1。
            接下来的参数是轮廓的颜色和厚度。
        """
        cv2.drawContours(image, contours, i, (0, 0, 255), 0)
    return image

全部代码

import numpy as np
import cv2
import math
from matplotlib import pyplot as plt


# 绘制直方图
def histogram(img):
    # 判断数据类型
    if img.dtype == 'uint8':
        hist = np.zeros(256)
        l = 256
    elif img.dtype == 'uint16':
        hist = np.zeros(65536)
        l = 65536
    else:
        return 0
    for i in range(img.shape[0]):
        for j in range(img.shape[1]):
            hist[img[i][j]] += 1
    return l, hist


# 直方图均衡化
def level(img):
    # 绘制直方图
    L, hist = histogram(img)
    # 建一个空数组
    Cumulative_histogram = {}
    tmp = 0
    for i in range(hist.size):
        if hist[i] != 0:
            Cumulative_histogram[i] = hist[i] / img.size + tmp
            tmp = Cumulative_histogram[i]

    for i in Cumulative_histogram.keys():
        tmp = math.floor((L - 1) * Cumulative_histogram[i] + 0.5)
        Cumulative_histogram[i] = tmp

    new_img = np.array(img)
    for i in range(img.shape[0]):
        for j in range(img.shape[1]):
            if img[i][j] in Cumulative_histogram.keys():
                new_img[i][j] = Cumulative_histogram[img[i][j]]

    return new_img


# 分块直方图均衡化,获取局部增强结果
def devide(img):
    # 图像分块
    m, n = img.shape
    img1 = img[:int(m / 2), :int(n / 2)]
    img2 = img[:int(m / 2), int(n / 2):]
    img3 = img[int(m / 2):, :int(n / 2)]
    img4 = img[int(m / 2):, int(n / 2):]

    # 对分块后的直方图均衡化
    '''
    方法一
    ret1 = cv2.equalizeHist(img1)
    ret2 = cv2.equalizeHist(img2)
    ret3 = cv2.equalizeHist(img3)
    ret4 = cv2.equalizeHist(img4)
    '''

    # 方法二
    ret1 = level(img1)
    ret2 = level(img2)
    ret3 = level(img3)
    ret4 = level(img4)

    # 合并图像
    level1_img = np.zeros(img.shape)
    level1_img[:math.ceil(m / 2), :math.ceil(n / 2)] = ret1
    level1_img[:math.ceil(m / 2), math.ceil(n / 2):] = ret2
    level1_img[math.ceil(m / 2):, :math.ceil(n / 2)] = ret3
    level1_img[math.ceil(m / 2):, math.ceil(n / 2):] = ret4
    return level1_img


# 卷积
def imgConvolve(image, kernel):
    '''
    :param image: 图片矩阵
    :param kernel: 滤波窗口
    :return:卷积后的矩阵
    '''

    img_h, img_w = image.shape
    kernel_h, kernel_w = kernel.shape
    # padding
    padding_h = int((kernel_h - 1) / 2)
    padding_w = int((kernel_w - 1) / 2)

    convolve_h = int(img_h + 2 * padding_h)
    convolve_W = int(img_w + 2 * padding_w)

    # 分配空间
    img_padding = np.zeros((convolve_h, convolve_W))
    # 中心填充图片
    img_padding[padding_h:padding_h + img_h, padding_w:padding_w + img_w] = image[:, :]
    # 卷积结果
    image_convolve = np.zeros(image.shape)
    # 卷积
    for i in range(padding_h, padding_h + img_h):
        for j in range(padding_w, padding_w + img_w):
            image_convolve[i - padding_h][j - padding_w] = int(
                np.sum(img_padding[i - padding_h:i + padding_h + 1, j - padding_w:j + padding_w + 1] * kernel))

    return image_convolve


# Prewitt算子边缘锐化
def prewittEdge(image, prewitt_x, prewitt_y):
    '''
    :param image: 图片矩阵
    :param prewitt_x: 竖直方向
    :param prewitt_y: 水平方向
    :return:处理后的矩阵
    '''
    img_X = imgConvolve(image, prewitt_x)
    img_Y = imgConvolve(image, prewitt_y)

    img_prediction = np.zeros(img_X.shape)
    for i in range(img_prediction.shape[0]):
        for j in range(img_prediction.shape[1]):
            img_prediction[i][j] = max(img_X[i][j], img_Y[i][j])
    return img_prediction


# 图像二值化
def custom_threshold(image):
    # 计算图像均值
    h, w = image.shape[:2]
    m = np.reshape(image, [1, w * h])
    mean = m.sum() / (w * h)
    # 给定参数二值化
    ret, binary = cv2.threshold(image, mean, 255, cv2.THRESH_BINARY)
    return binary


# 轮廓拟合
def contours_demo(image):
    # 原始二值化得到的图像是float类型,进行类型转换
    image = np.array(image, dtype='uint8')
    """
        cloneimage 显示图像,查找轮廓
        需要注意的是此处是cv2版本
        cv在2和4版本里面cv2.findContours需要的是两个参数
        在3版本里面只需要两个参数改成
        contours, heriachy = cv2.findContours(image, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
        即可
    """
    cloneimage, contours, heriachy = cv2.findContours(image, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
    # 绘制图像
    for i, contour in enumerate(contours):
        """
            函数cv2.drawContours()被用来绘制轮廓。
            第一个参数是一张图片,可以是原图或者其他。
            第二个参数是轮廓,也可以说是cv2.findContours()找出来的点集,一个列表。
            第三个参数是对轮廓(第二个参数)的索引,当需要绘制独立轮廓时很有用,若要全部绘制可设为-1。
            接下来的参数是轮廓的颜色和厚度。
        """
        cv2.drawContours(image, contours, i, (0, 0, 255), 0)
    return image

# 展示
def show(img, img1, img2, img3, img4, img5, img6, img7):
    '''
    :param img: 原图
    :param img1: 局部增强
    :param img2: 边缘锐化
    :param img3: 边缘锐化
    :param img4: 二值化
    :param img5: 二值化
    :param img6: 提取边缘轮廓
    :param img7: 提取边缘轮廓
    :return: 结果显示
    '''
    plt.subplot(241), plt.imshow(img, cmap='gray')
    plt.title('primary'), plt.xticks([]), plt.yticks([])
    plt.subplot(242), plt.imshow(img1, cmap='gray')
    plt.title('level_img'), plt.xticks([]), plt.yticks([])
    plt.subplot(243), plt.imshow(img2, cmap='gray')
    plt.title('prewitt_1'), plt.xticks([]), plt.yticks([])
    plt.subplot(244), plt.imshow(img3, cmap='gray')
    plt.title('prewitt_2'), plt.xticks([]), plt.yticks([])
    plt.subplot(245), plt.imshow(img4, cmap='gray')
    plt.title('binaryzation_1'), plt.xticks([]), plt.yticks([])
    plt.subplot(246), plt.imshow(img5, cmap='gray')
    plt.title('binaryzation_2'), plt.xticks([]), plt.yticks([])
    plt.subplot(247), plt.imshow(img6, cmap='gray')
    plt.title('Image_1'), plt.xticks([]), plt.yticks([])
    plt.subplot(248), plt.imshow(img7, cmap='gray')
    plt.title('Image_2'), plt.xticks([]), plt.yticks([])
    plt.show()
import numpy as np
import function


def run(img):
    # 分块均衡化直方图
    level_img = function.devide(img)

    # prewitt算子
    t_prewitt_1 = np.array([[-1, -1, -1], [0, 0, 0], [1, 1, 1]])
    t_prewitt_2 = np.array([[-1, 0, 1], [-1, 0, 1], [-1, 0, 1]])
    t_prewitt_3 = np.array([[0, 1, 1], [-1, 0, 1], [-1, -1, 0]])
    t_prewitt_4 = np.array([[-1, -1, 0], [-1, 0, 1], [0, 1, 1]])

    '''
        纵横方向
        原始图prewitt算子进行边缘锐化
    '''
    img_prewitt_1 = function.prewittEdge(img, t_prewitt_1, t_prewitt_2)
    '''
        对角线方向
        直方图均衡化后的prewitt算子进行边缘锐化 
    '''
    img_prewitt_2 = function.prewittEdge(level_img, t_prewitt_3, t_prewitt_4)

    # 图像二值化
    binaryzation_1 = function.custom_threshold(img_prewitt_1)
    binaryzation_2 = function.custom_threshold(img_prewitt_2)

    # 轮廓拟合
    Image_1 = function.contours_demo(binaryzation_1)
    Image_2 = function.contours_demo(binaryzation_2)

    # 展示
    function.show(img,
                  level_img,
                  img_prewitt_1, img_prewitt_2,
                  binaryzation_1, binaryzation_2,
                  Image_1, Image_2)
import run
import cv2

'''
          ┏┓   ┏┓+ +
        ┏┛┻━━━┛┻┓ + +
        ┃       ┃  
        ┃   ━   ┃ ++ + + +
        ████━████ ┃+
        ┃       ┃ +
        ┃   ┻   ┃
        ┃       ┃ + +
        ┗━┓   ┏━┛
           ┃   ┃           
           ┃   ┃ + + + +
           ┃   ┃ Code is far away from bug with the animal protecting       
           ┃   ┃ + 神兽保佑,永无bug  
           ┃   ┃
           ┃   ┃  +         
             ┃    ┗━━━┓ + +
           ┃        ┣┓
           ┃        ┏┛
           ┗┓┓┏━┳┓┏┛ + + + +
            ┃┫┫ ┃┫┫
            ┗┻┛ ┗┻┛+ + + +
'''

if __name__ == '__main__':
    # 读入图片
    img = cv2.imread('../image/lena-gray.png', -1)
    # 显示结果
    run.run(img)

成果展示

在这里插入图片描述

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值