数字图像处理实验思考题

数字图像处理实验的思考题汇总(实验三到实验六)。实验一没有思考题,实验二本人的实现效果不是很好,就不放出来献丑了。

实验三

通过鼠标操作在图像上选取任意4边形区域,通过仿射变换到指定的矩形区域。例如梯形到矩形的变换。提示:应用场景,例如将手机拍摄的梯形图片,通过几何操作,变的方方正正。

import cv2
import numpy as np


# 顺时针
def on_mouse(event, x, y, flag, param):
    global X, Y, img, index, ix, iy, jx, jy
    if event == cv2.EVENT_LBUTTONUP and index < 4:
        X[index], Y[index] = x, y
        if index == 0:
            cv2.line(img, (x, y), (x, y), (0, 0, 255), 3)
        elif index == 1:
            cv2.line(img, (x, y), (X[index - 1], Y[index - 1]), (0, 0, 255), 3)
        elif index == 2:
            cv2.line(img, (x, y), (X[index - 1], Y[index - 1]), (0, 0, 255), 3)
        elif index == 3:
            cv2.line(img, (x, y), (X[index - 1], Y[index - 1]), (0, 0, 255), 3)
            cv2.line(img, (x, y), (X[0], Y[0]), (0, 0, 255), 3)
        index += 1
    elif event == cv2.EVENT_LBUTTONDOWN and index == 4:
        ix, iy = x, y
    elif event == cv2.EVENT_LBUTTONUP and index == 4:
        cv2.rectangle(img, (ix, iy), (x, y), (0, 255, 0), 1)
        jx, jy = x, y
        index += 1


if __name__ == '__main__':
    img = cv2.imread('ppt.jpg')
    cols, rows = img.shape[:2]
    X = [-1, -1, -1, -1]
    Y = [-1, -1, -1, -1]
    ix, iy, jx, jy = -1, -1, -1, -1
    index = 0
    cv2.namedWindow('image')
    cv2.setMouseCallback('image', on_mouse)
    while 1:
        cv2.imshow('image', img)
        if index > 4:
            pts1 = np.float32([[X[0], Y[0]], [X[1], Y[1]], [X[2], Y[2]]])
            pts2 = np.float32([[ix, iy], [jx, iy], [jx, jy]])
            M = cv2.getAffineTransform(pts1, pts2)
            dst = cv2.warpAffine(img, M, (cols, rows))
            cv2.imshow('output', dst)
        if cv2.waitKey(20) & 0xFF == 27:
            break
    cv2.destroyAllWindows()

注:先点出要进行仿射变换的四边形的顶点(从左上角开始,顺时针),再拖拽鼠标左键框出要变换到的矩形位置。

效果:

原图像

实验四

  1. 给出彩色图像Fig6,请在HSI空间对图像的亮度分量进行均衡化,观察彩色图像效果。

注:opencv中没有转为HSI空间的库函数,需要自己写,但效果不是很好。故转为HSV空间实现。

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


if __name__ == '__main__':
    rgb_img = cv2.imread("Fig6.png")
    hsv_img = cv2.cvtColor(rgb_img, cv2.COLOR_BGR2HSV)
    cv2.imshow("hsv", hsv_img)
    h, s, v = cv2.split(hsv_img)
    equ = cv2.equalizeHist(v)
    res_img = cv2.merge([h, s, equ])
    cv2.imshow("hsv_equ", res_img)
    ans_img = cv2.cvtColor(res_img, cv2.COLOR_HSV2BGR)
    cv2.imshow("original", rgb_img)
    cv2.imshow("ans", ans_img)
    key = cv2.waitKey(0) & 0xFF
    if key == ord('q'):
        cv2.destroyAllWindows()

效果:

原图像

  1. 对同一幅图像Fig6在B、G、R空间逐一做均衡化处理,观察最终的图像与思考题1中的结果异同。

    import cv2
    import numpy
    from matplotlib import pyplot as plt
    
    
    if __name__ == '__main__':
        img = cv2.imread('Fig6.png')
        cv2.imshow('Fig6', img)
        b, g, r = cv2.split(img)
        b = cv2.equalizeHist(b)
        g = cv2.equalizeHist(g)
        r = cv2.equalizeHist(r)
        res = cv2.merge([b, g, r])
        cv2.imshow('res', res)
        if cv2.waitKey(0) & 0xFF == 'q':
            cv2.destroyAllWindows()

    效果:

    原图像

  2. 编程实现直方图规定化的处理程序;给定图像Fig7A和图像Fig7B,把Fig7A图像直方图规范化为接近Fig7B图像直方图的分布。

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

img1 = cv2.imread('Fig7A.jpg')
img2 = cv2.imread('Fig7B.jpg')

img_hsv1 = cv2.cvtColor(img1, cv2.COLOR_BGR2HSV)  # bgr转hsv
img_hsv2 = cv2.cvtColor(img2, cv2.COLOR_BGR2HSV)

color = ('h', 's', 'v')

for i, col in enumerate(color):
    # histr = cv2.calcHist([img_hsv1], [i], None, [256], [0, 256])
    hist1, bins = np.histogram(img_hsv1[:, :, i].ravel(), 256, [0, 256])
    hist2, bins = np.histogram(img_hsv2[:, :, i].ravel(), 256, [0, 256])
    cdf1 = hist1.cumsum()  # 灰度值0-255的累计值数组
    cdf2 = hist2.cumsum()
    cdf1_hist = hist1.cumsum() / cdf1.max()  # 灰度值的累计值的比率
    cdf2_hist = hist2.cumsum() / cdf2.max()
    # 256*256的二维数组
    diff_cdf = [[0 for j in range(256)] for k in range(256)]  # diff_cdf 里是每2个灰度值比率间的差值
    for j in range(256):
        for k in range(256):
            diff_cdf[j][k] = abs(cdf1_hist[j] - cdf2_hist[k])

    lut = [0 for j in range(256)]  # 映射表
    for j in range(256):
        min = diff_cdf[j][0]
        index = 0
        for k in range(256):  # 直方图规定化的映射原理
            if min > diff_cdf[j][k]:
                min = diff_cdf[j][k]
                index = k
        lut[j] = ([j, index])

    h = int(img_hsv1.shape[0])
    w = int(img_hsv1.shape[1])
    for j in range(h):  # 对原图像进行灰度值的映射
        for k in range(w):
            img_hsv1[j, k, i] = lut[img_hsv1[j, k, i]][1]

hsv_img1 = cv2.cvtColor(img_hsv1, cv2.COLOR_HSV2BGR)  # hsv转bgr
hsv_img2 = cv2.cvtColor(img_hsv2, cv2.COLOR_HSV2BGR)

cv2.namedWindow('firstpic', 0)
cv2.resizeWindow('firstpic', 670, 900)
cv2.namedWindow('targetpic', 0)
cv2.resizeWindow('targetpic', 670, 900)
cv2.namedWindow('defpic', 0)
cv2.resizeWindow('defpic', 670, 900)

cv2.imshow('firstpic', img1)
cv2.imshow('targetpic', img2)
# cv2.imshow('img1', img_hsv1)
cv2.imshow('defpic', hsv_img1)

cv2.waitKey(0)
cv2.destroyAllWindows()

效果:

Fig7A

Fig7B

实验五

对child.jpg图像的灰度图像进行高通、带通、低通滤波后的结果分别表示彩色图像B、G、R分量。根据颜色分析观察图像中空间频率变化快慢的区域。

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

if __name__ == '__main__':
    index = 30
    thre = 10
    img_ori = cv2.imread('test.png')
    img = cv2.cvtColor(img_ori, cv2.COLOR_BGR2GRAY)
    f = np.fft.fft2(img)
    fshift = np.fft.fftshift(f)
    rows, cols = fshift.shape
    rrow = rows // 2
    ccol = cols // 2
    # 高通
    mask1 = np.ones((rows, cols), np.uint8)
    mask1[rrow - index: rrow + index, ccol - index: ccol + index] = 0
    # 带通
    mask2 = np.zeros((rows, cols), np.uint8)
    mask2[rrow - index: rrow + index, ccol - index: ccol + index] = 1
    mask2[rrow - thre: rrow + thre, ccol - thre: ccol + thre] = 0
    # 低通
    mask3 = np.zeros((rows, cols), np.uint8)
    mask3[rrow - index: rrow + index, ccol - index: ccol + index] = 1
    f1 = fshift * mask1
    f2 = fshift * mask2
    f3 = fshift * mask3
    f_ishift1 = np.fft.ifftshift(f1)
    f_ishift2 = np.fft.ifftshift(f2)
    f_ishift3 = np.fft.ifftshift(f3)
    HPF = np.abs(np.fft.ifft2(f_ishift1))
    BPF = np.abs(np.fft.ifft2(f_ishift2))
    LPF = np.abs(np.fft.ifft2(f_ishift3))
    # plt.subplot(321), plt.imshow(img, cmap='gray'), plt.title('Original'), plt.xticks([]), plt.yticks([])
    plt.subplot(331), plt.imshow(HPF, cmap='gray'), plt.title('HPF'), plt.xticks([]), plt.yticks([])
    plt.subplot(332), plt.imshow(BPF), plt.title('BPF'), plt.xticks([]), plt.yticks([])
    plt.subplot(333), plt.imshow(LPF, cmap='gray'), plt.title('LPF'), plt.xticks([]), plt.yticks([])
    # rgb
    ans_img = cv2.merge([HPF, BPF, LPF])
    plt.subplot(334), plt.imshow(ans_img.astype('uint8')), plt.title('HBL'), plt.xticks([]), plt.yticks([])
    ans_img = cv2.merge([HPF, LPF, BPF])
    plt.subplot(335), plt.imshow(ans_img.astype('uint8')), plt.title('HLB'), plt.xticks([]), plt.yticks([])
    ans_img = cv2.merge([BPF, HPF, LPF])
    plt.subplot(336), plt.imshow(ans_img.astype('uint8')), plt.title('BHL'), plt.xticks([]), plt.yticks([])
    ans_img = cv2.merge([BPF, LPF, HPF])
    plt.subplot(337), plt.imshow(ans_img.astype('uint8')), plt.title('BLH'), plt.xticks([]), plt.yticks([])
    ans_img = cv2.merge([LPF, BPF, HPF])
    plt.subplot(338), plt.imshow(ans_img.astype('uint8')), plt.title('LBH'), plt.xticks([]), plt.yticks([])
    ans_img = cv2.merge([LPF, HPF, BPF])
    plt.subplot(339), plt.imshow(ans_img.astype('uint8')), plt.title('LHB'), plt.xticks([]), plt.yticks([])
    plt.show()

效果:

原图像

实验六

请独自完成视频图像中蓝色物体的跟踪。请用矩形框在视频中标出给跟踪的目标。

import cv2
import numpy as np

if __name__ == '__main__':
    cap = cv2.VideoCapture(0)
    while 1:
        # 获取每一帧
        ret, frame = cap.read()
        # 转换到HSV
        hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
        # 设定蓝色的阈值
        lower_blue = np.array([110, 50, 50])
        upper_blue = np.array([130, 255, 255])
        # 根据阈值构建掩模
        mask = cv2.inRange(hsv, lower_blue, upper_blue)
        # 开操作
        kernel = np.ones((8, 8), np.uint8)
        mask = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel)
        xy = np.where(mask == 255)
        y = list(xy)[0]
        x = list(xy)[1]
        x_min, x_max = min(x), max(x)
        y_min, y_max = min(y), max(y)
        cv2.rectangle(frame, (x_min, y_min), (x_max, y_max), (0, 255, 0), 2)
        # mask = cv2.erode(mask, kernel, iterations=1)
        # 对原图像和掩模进行位运算
        res = cv2.bitwise_and(frame, frame, mask=mask)
        # 显示图像
        cv2.imshow('frame', frame)
        cv2.imshow('mask', mask)
        cv2.imshow('res', res)
        k = cv2.waitKey(5) & 0xFF
        if k == 27:
            break
    # 关闭窗口
    cv2.destroyAllWindows()

用蓝色瓶盖(如芬达)。效果不好的话需要调整阈值参数和开操作的模板大小。


数字图像处理实验思考题
https://lmc20020909.github.io/数字图像处理实验思考题/
作者
Liu Mingchen
发布于
2022年11月14日
许可协议