边缘检测和图像插值(生成皮卡丘的轮廓!&& 放大图片n倍!)

文章目录

    • 一、实验介绍
      • (1)实验目的
      • (2)测试图像
      • (3)实验内容
    • 二、编写程序实现对图片的边缘检测
      • (1)canny边缘检测代码
      • (2)结果
      • (3)分析
    • 三、最近邻插值
      • (1)代码
      • (2)结果
    • 四、双线性插值
      • (1)代码
      • (2)结果
    • 五、双立方插值
      • (1)代码
      • (2)结果
    • 六、结果分析
    • 参考

一、实验介绍

(1)实验目的

  • 掌握边缘检测和图像插值
  • 语言:python

(2)测试图像

边缘检测和图像插值(生成皮卡丘的轮廓!&& 放大图片n倍!)_第1张图片

(3)实验内容

  • 编写程序实现对图片的边缘检测。
  • 编写程序实现对图像的插值

二、编写程序实现对图片的边缘检测

(1)canny边缘检测代码

  • 编写程序实现线性、高斯核、拉普拉斯核的的SVM分类器设计。
import cv2
img = cv2.imread("picaqu.jpg", 0)
cv2.imwrite("canny.jpg", cv2.Canny(img, 200, 300))
cv2.imshow("canny", cv2.imread("canny.jpg"))
cv2.waitKey()
cv2.destroyAllWindows()

(2)结果

边缘检测和图像插值(生成皮卡丘的轮廓!&& 放大图片n倍!)_第2张图片

(3)分析

  • 可以发现canny边缘检测算子的效果较为不错

三、最近邻插值

  • 将图像由500x283增大为2048x1160

(1)代码

import cv2
import numpy as np
IMG_PATH = "./picaqu.jpg"
NUM2 = 2048
NUM1 = int(NUM2 * 283 / 500)
def function(img):
    height, width, channels = img.shape
    emptyImage = np.zeros((NUM1, NUM2, channels), np.uint8)
    sh = NUM1 / height
    sw = NUM2 / width
    for i in range(NUM1):
        for j in range(NUM2):
            x = int(i / sh)
            y = int(j / sw)
            emptyImage[i, j] = img[x, y]
    return emptyImage
img = cv2.imread(IMG_PATH)
zoom = function(img)
cv2.imwrite("./nearest neighbor.jpg", zoom)
print('完成')

(2)结果

边缘检测和图像插值(生成皮卡丘的轮廓!&& 放大图片n倍!)_第3张图片

四、双线性插值

  • 将图像由500x283增大为2048x1160

(1)代码

import cv2
import numpy as np
IMG_PATH = "./picaqu.jpg"
NUM2 = 2048
NUM1 = int(NUM2 * 283 / 500)
def function(img):
    height, width, channels = img.shape
    emptyImage = np.zeros((NUM1, NUM2, channels), np.uint8)
    value = [0, 0, 0]
    sh = NUM1 / height
    sw = NUM2 / width
    for i in range(NUM1):
        for j in range(NUM2):
            x = i / sh
            y = j / sw
            p = (i + 0.0) / sh - x
            q = (j + 0.0) / sw - y
            x = int(x) - 1
            y = int(y) - 1
            for k in range(3):
                if x + 1 < NUM1 and y + 1 < NUM2:
                    value[k] = int(
                        img[x, y][k] * (1 - p) * (1 - q) + img[x, y + 1][k] * q * (1 - p) + img[x + 1, y][k] * (
                                    1 - q) * p + img[x + 1, y + 1][k] * p * q)
            emptyImage[i, j] = (value[0], value[1], value[2])
    return emptyImage
img = cv2.imread(IMG_PATH)
zoom = function(img)
cv2.imwrite("./Bilinear Interpolation.jpg", zoom)
# cv2.waitKey(0)
print('完成')

(2)结果

边缘检测和图像插值(生成皮卡丘的轮廓!&& 放大图片n倍!)_第4张图片

五、双立方插值

  • 将图像由500x283增大为2048x1160

(1)代码

import cv2
import numpy as np

IMG_PATH = "./picaqu.jpg"
NUM2 = 2048
NUM1 = int(NUM2 * 283 / 500)

def S(x):
    x = np.abs(x)
    if 0 <= x < 1:
        return 1 - 2 * x * x + x * x * x
    if 1 <= x < 2:
        return 4 - 8 * x + 5 * x * x - x * x * x
    else:
        return 0


def function(img, m, n):
    height, width, channels = img.shape
    emptyImage = np.zeros((m, n, channels), np.uint8)
    sh = m / height
    sw = n / width
    for i in range(m):
        for j in range(n):
            x = i / sh
            y = j / sw
            p = (i + 0.0) / sh - x
            q = (j + 0.0) / sw - y
            x = int(x) - 2
            y = int(y) - 2
            A = np.array([
                [S(1 + p), S(p), S(1 - p), S(2 - p)]
            ])
            if x >= m - 3:
                m - 1
            if y >= n - 3:
                n - 1
            if x >= 1 and x <= (m - 3) and y >= 1 and y <= (n - 3):
                B = np.array([
                    [img[x - 1, y - 1], img[x - 1, y],
                     img[x - 1, y + 1],
                     img[x - 1, y + 1]],
                    [img[x, y - 1], img[x, y],
                     img[x, y + 1], img[x, y + 2]],
                    [img[x + 1, y - 1], img[x + 1, y],
                     img[x + 1, y + 1], img[x + 1, y + 2]],
                    [img[x + 2, y - 1], img[x + 2, y],
                     img[x + 2, y + 1], img[x + 2, y + 1]],

                ])
                C = np.array([
                    [S(1 + q)],
                    [S(q)],
                    [S(1 - q)],
                    [S(2 - q)]
                ])
                blue = np.dot(np.dot(A, B[:, :, 0]), C)[0, 0]
                green = np.dot(np.dot(A, B[:, :, 1]), C)[0, 0]
                red = np.dot(np.dot(A, B[:, :, 2]), C)[0, 0]

                # ajust the value to be in [0,255]
                def adjust(value):
                    if value > 255:
                        value = 255
                    elif value < 0:
                        value = 0
                    return value

                blue = adjust(blue)
                green = adjust(green)
                red = adjust(red)
                emptyImage[i, j] = np.array([blue, green, red], dtype=np.uint8)

    return emptyImage


img = cv2.imread(IMG_PATH)
zoom = function(img, NUM1, NUM2)
cv2.imwrite("./cubic.jpg", zoom)
print('完成')

(2)结果

边缘检测和图像插值(生成皮卡丘的轮廓!&& 放大图片n倍!)_第5张图片

六、结果分析

  • 使用canny边缘检测算子所得的结果较好,可以看出所有的边缘信息都被检测出来了
  • 图像插值算法中,最邻近插值,双线性插值,双三次插值效果都较好,能够很好的放大图像,得到满意的结果

参考

无聊之作-图像插值方法python实现

你可能感兴趣的:(机器学习)