东南大学《数字图像处理》课程作业 3 - 灰度图放大

说明.pdf.1

说明.pdf.2

程序代码

# coding: utf-8

'''
东南大学《数字图像处理》课程 作业3 - 灰度图放大
09017227 卓旭 written with Python 3

本程序内灰度图像作为二维数组,存储顺序为[行][列],像素点坐标表示为img[x][y],坐标系为
O--------> [y axis]
|
|
V [x axis]
'''

import imageio
import numpy as np
import cv2 # OpenCV仅用于显示图片,未使用其中的resize函数

IMAGE_PATH='./Img_Zoom.bmp'
ZOOM_IN_RATE=5

'''
  读入灰度图像,转为二维numpy数组
'''
def readImage(imagePath):
  return imageio.imread(imagePath)

'''
  利用放大倍率计算目标图像在原图像的对应视区,返回四元组 (左上角x坐标, 左上角y坐标, 宽度, 高度)
'''
def getViewport(sourceImage, zoomInRate):
  centerX, centerY = list(map(lambda x: x / 2, sourceImage.shape))
  # width, height = list(map(lambda x: x / zoomInRate, sourceImage.shape))
  height, width = list(map(lambda x: x / zoomInRate, sourceImage.shape)) # 这里之前写错了,这次提交修改
  leftTopX, leftTopY = centerX - height / 2, centerY - width / 2
  return (leftTopX, leftTopY, width, height)

'''
  最近邻插值
'''
def nearestInterp(sourceImage, zoomInRate):
  leftTopX, leftTopY, _, _ = getViewport(sourceImage, ZOOM_IN_RATE)
  targetImage = np.zeros(sourceImage.shape, dtype=np.uint8)  # 生成全0目标图像,准备填充,数据类型为8bit数
  # 循环目标图像
  for i in range(targetImage.shape[0]):
    for j in range(targetImage.shape[1]):
      # 目标图像中一像素的步进,在原图像中相当于 1/zoomInRate 像素的步进
      # 利用四舍五入,自带取最近邻像素点的效果。半像素是分界线
      targetImage[i][j] = sourceImage[round(i / zoomInRate + leftTopX)][round(j / zoomInRate + leftTopY)]
  return targetImage

'''
  双线性插值
'''
def bilinearInterp(sourceImage, zoomInRate):
  leftTopX, leftTopY, _, _ = getViewport(sourceImage, ZOOM_IN_RATE)
  targetImage = np.zeros(sourceImage.shape, dtype=np.uint8)  # 生成全0目标图像,准备填充,数据类型为8bit数
  F = lambda point: sourceImage[point[0]][point[1]] # 返回原图指定坐标处的灰度值
  # 循环目标图像
  for i in range(targetImage.shape[0]):
    for j in range(targetImage.shape[1]):
      # 目标图像中一像素的步进,在原图像中相当于 1/zoomInRate 像素的步进
      # 算出原图像四个插值数据点的坐标
      p00 = [int(i / zoomInRate + leftTopX), int(j / zoomInRate + leftTopY)]
      p01 = [int(i / zoomInRate + leftTopX), int(j / zoomInRate + leftTopY) + 1]
      p10 = [int(i / zoomInRate + leftTopX) + 1, int(j / zoomInRate + leftTopY)]
      p11 = [int(i / zoomInRate + leftTopX) + 1, int(j / zoomInRate + leftTopY) + 1]
      # 当前点在原图像的坐标
      p = [i / zoomInRate + leftTopX, j / zoomInRate + leftTopY]
      # 假设四个插值数据点的权重均相同,该公式的推导请看附带文档
      x0 = p00[0]; x1 = x0 + 1; y0 = p00[1]; y1 = y0 + 1; x = p[0]; y = p[1]
      targetImage[i][j] = (x1 - x) * (y1 - y) * F(p00) + \
                          (x1 - x) * (y - y0) * F(p01) + \
                          (x - x0) * (y1 - y) * F(p10) + \
                          (x - x0) * (y - y0) * F(p11)
  return targetImage

if __name__ == '__main__':
  sourceImage = readImage(IMAGE_PATH)
  print("计算最近邻插值中...")
  targetImage1 = nearestInterp(sourceImage, ZOOM_IN_RATE)
  print("计算双线性插值中...")
  targetImage2 = bilinearInterp(sourceImage, ZOOM_IN_RATE)
  print("计算完成,开始依次显示")
  cv2.imshow("nearestInterp", targetImage1)
  cv2.waitKey(0)
  imageio.imwrite('nearestInterp.bmp', targetImage1)
  print("最近邻插值保存成功")
  cv2.imshow("bilinearInterp", targetImage2)
  imageio.imwrite('bilinearInterp.bmp', targetImage2)
  print("双线性插值保存成功")
  cv2.waitKey(0)
posted @ 2021-02-07 23:34  z0gSh1u  阅读(232)  评论(0编辑  收藏  举报