返回主目录

5 图像美化效果

5-1 美化效果章节介绍

图像特效分为以下几个,分别是:

  1. 案例1:直方图
  2. 案例2:直方图均衡化
  3. 案例3:亮度增强
  4. 案例4:磨皮美白
  5. 案例5:图片滤波
  6. 案例6:高斯滤波

5-2 彩色图片直方图

直方图用的是OpenCV里面的calcHist函数 ,其定义如下:

cv2.calcHist(images, channels, mask, histSize, ranges[, hist[, accumulate ]])

calcHist函数具体参数定义如下:

  • imaes:输入的图像;
  • channels:选择图像的通道
  • mask:掩膜,是一个大小和image一样的np数组,其中把需要处理的部分指定为1 ,不需要处理的部分指定为0,一般设置为None,表示处理整幅图像
  • histSize:使用多少个bin(柱子) ,一般为256
  • ranges:像素值的范围 ,一般为[0,255]表示0~255
  • [, hist[, accumulate ]]这两个参数基本不用管。
  • 注:除了mask,其他四个参数都要带[]号 。

代码如下:

# 彩色图片直方图
import cv2
import numpy as np


def ImageHist(image, channel):
    color = (0, 0, 0)  # 初始化一个color
    window_name = 'Gray'  # 初始化一个窗口名
    if channel == 0:  # 第一个通道为蓝色B
        color = (255, 0, 0)
        window_name = 'B Hist'
    elif channel == 1:  # 第二个通道为绿色G
        color = (0, 255, 0)
        window_name = 'G Hist'
    elif channel == 2:  # 第三个通道为红色R
        color = (0, 0, 255)
        window_name = 'R Hist'
    # hist是一个shape为(256,1)的数组,表示0-255每个像素值对应的像素个数	,下标即为相应的像素值
    hist = cv2.calcHist([image], [0], None, [256], [0.0, 255.0])
    # 获取hist的最小最大值和最小最大值的索引
    min_value, max_value, min_index, max_index = cv2.minMaxLoc(hist)
    # 创建一个模板
    hist_img = np.zeros([256, 256, 3], np.uint8)
    for h in range(256):
        inten_normal = int(hist[h] * 256 / max_value)
        cv2.line(hist_img, (h, 256), (h, 256 - inten_normal), color)
    cv2.imshow(window_name, hist_img)
    return hist_img


img = cv2.imread('00.jpg', 1)
cv2.imshow('img', img)
channels = cv2.split(img)  # 使用split将彩色图像拆分成三个通道
for i in range(0, 3):
    ImageHist(channels[i], i)  # 调用ImageHist函数,第一个参数为B	、G、R三原色图片,第二个参数为通道索引
cv2.waitKey(0)

运行结果如下:

将代码稍微改一改 ,就可以显示灰度图像直方图啦,代码如下:

# 灰色图像直方图
import cv2
import numpy as np


def ImageHist(image):
    # hist是一个shape为(256,1)的数组,表示0-255每个像素值对应的像素个数	,下标即为相应的像素值
    hist = cv2.calcHist([image], [0], None, [256], [0.0, 255.0])
    # 获取hist的最小最大值和最小最大值的索引
    min_value, max_value, min_index, max_index = cv2.minMaxLoc(hist)
    # 创建一个模板
    hist_img = np.zeros([256, 256, 3], np.uint8)
    for h in range(256):
        inten_normal = int(hist[h] * 256 / max_value)
        cv2.line(hist_img, (h, 256), (h, 256 - inten_normal), 255)
    cv2.imshow('histImg', hist_img)
    return hist_img


img = cv2.imread('01.jpg', 1)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
cv2.imshow('gray', gray)
ImageHist(gray)
cv2.waitKey(0)

运行结果如下:

5-3 直方图均衡化

直方图均衡化要用到的函数是cv2.equalizeHist()。

  • 灰度图像直方图均衡化可以直接使用cv2.equalizeHist()。
  • 彩色图像直方图均衡化需要将原图像进行拆分,使用cv2.split函数可以将图像拆分,拆分之后对单通道直方图进行均衡化 ,最后需要将均衡化后的图像合并,使用的是cv2.merge函数 。
  • YUV图像直方图均衡化也需要拆分再合并才行。
    具体代码如下:
import cv2

img = cv2.imread('02.jpg', 1)
# 灰色图像 直方图均衡化
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
cv2.imshow('gray', gray)  # 灰色图像
gray_dst = cv2.equalizeHist(gray)
cv2.imshow('gray_dst', gray_dst)  # 灰色图像均衡化

# 彩色图像 直方图均衡化
cv2.imshow('img', img)  # 彩色图像
(b, g, r) = cv2.split(img)  # 通道拆分
b_hist = cv2.equalizeHist(b)
g_hist = cv2.equalizeHist(g)
r_hist = cv2.equalizeHist(r)
img_dst = cv2.merge((b_hist, g_hist, r_hist))  # 通道合并
cv2.imshow('img_dst', img_dst)  # 彩色图像均衡化

# YUV图像 直方图均衡化
imgYUV = cv2.cvtColor(img, cv2.COLOR_BGR2YCrCb)
cv2.imshow('imgYUV', imgYUV)  # YUV图像
channelYUV = cv2.split(imgYUV)  # 通道拆分
channelYUV[0] = cv2.equalizeHist(channelYUV[0])
channels = cv2.merge(channelYUV)  # 通道合并
yuv_dst = cv2.cvtColor(channels, cv2.COLOR_YCrCb2BGR)
cv2.imshow('yuv_dst', yuv_dst)

cv2.waitKey(0)

运行结果如下:

5-4 图片修补

运行代码如下:

import cv2
import numpy as np

img = cv2.imread('03.jpg', 1)
cv2.imshow('src', img)
print(img.shape)
for i in range(200, 300):
    img[i, 200] = (255, 255, 255)
    img[i, 200 + 1] = (255, 255, 255)
    img[i, 200 - 1] = (255, 255, 255)
for i in range(150, 250):
    img[250, i] = (255, 255, 255)
    img[250 + 1, i] = (255, 255, 255)
    img[250 - 1, i] = (255, 255, 255)
cv2.imwrite('03damaged.jpg', img)

damaged = cv2.imread('03damaged.jpg', 1)
cv2.imshow('damaged', damaged)
damagedInfo = damaged.shape
height = damagedInfo[0]
width = damagedInfo[1]
paint = np.zeros((height, width, 1), np.uint8)
for i in range(200, 300):
    paint[i, 200] = 255
    paint[i, 200 + 1] = 255
    paint[i, 200 - 1] = 255
for i in range(150, 250):
    paint[250, i] = 255
    paint[250 + 1, i] = 255
    paint[250 - 1, i] = 255
cv2.imshow('paint', paint)
# 1.src 2.mask
imgDst = cv2.inpaint(damaged, paint, 3, cv2.INPAINT_TELEA)
cv2.imshow('imgDst', imgDst)
cv2.waitKey(0)

运行结果如下:

5-5 灰度直方图源码

代码如下:

# 1 0-255 2 概率
# 本质:统计每个像素灰度出现的概率,横坐标为0-255(256个数),纵坐标是出现的概率p
import cv2
import numpy as np
import matplotlib.pyplot as plt

img = cv2.imread('15.jpg', 1)
imgInfo = img.shape
height = imgInfo[0]
width = imgInfo[1]
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
count = np.zeros(256, np.float)

for i in range(0, height):
    for j in range(0, width):
        pixel = gray[i, j]  # 获取每一个灰度等级的像素
        index = int(pixel)
        count[index] = count[index] + 1

for i in range(0, 255):
    count[i] = count[i] / (height * width)

x = np.linspace(0, 255, 256)
y = count
plt.bar(x, y, 0.9, alpha=1, color='b')
plt.show()
cv2.waitKey(0)

运行结果如下:

5-6 彩色直方图源码

代码如下:

# 本质:统计每个像素灰度 出现的概率 0-255 p
import cv2
import numpy as np
import matplotlib.pyplot as plt

img = cv2.imread('04.jpg', 1)
imgInfo = img.shape
height = imgInfo[0]
width = imgInfo[1]

count_b = np.zeros(256, np.float)
count_g = np.zeros(256, np.float)
count_r = np.zeros(256, np.float)

for i in range(0, height):
    for j in range(0, width):
        (b, g, r) = img[i, j]
        index_b = int(b)
        index_g = int(g)
        index_r = int(r)
        count_b[index_b] = count_b[index_b] + 1
        count_g[index_g] = count_g[index_g] + 1
        count_r[index_r] = count_r[index_r] + 1

for i in range(0, 256):
    count_b[i] = count_b[i] / (height * width)
    count_g[i] = count_g[i] / (height * width)
    count_r[i] = count_r[i] / (height * width)

x = np.linspace(0, 255, 256)  # 将0-255按照等分成256份

plt.subplot(221)
plt.imshow(img)
plt.title('img')

yb = count_b
plt.subplot(222)
plt.title('b')
plt.bar(x, yb, 0.9, alpha=1, color='b')

yg = count_g
plt.subplot(223)
plt.title('g')
plt.bar(x, yg, 0.9, alpha=1, color='g')

yr = count_r
plt.subplot(224)
plt.title('r')
plt.bar(x, yr, 0.9, alpha=1, color='r')

plt.tight_layout()
plt.show()
cv2.waitKey(0)

运行结果如下:

5-7 灰度直方图均衡化

代码如下:

# 本质:统计每个像素灰度 出现的概率 0-255 p
# 累计概率
# 1 0.2  0.2
# 2 0.3  0.5
# 3 0.1  0.6
# 256
# 100 0.5 255*0.5 = new
import cv2
import numpy as np

img = cv2.imread('05.jpg', 1)
cv2.imshow('src', img)

imgInfo = img.shape
height = imgInfo[0]
width = imgInfo[1]
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
cv2.imshow('gray', gray)
count = np.zeros(256, np.float)
for i in range(0, height):
    for j in range(0, width):
        pixel = gray[i, j]
        index = int(pixel)
        count[index] = count[index] + 1

for i in range(0, 255):
    count[i] = count[i] / (height * width)

# 计算累计概率
sum1 = float(0)
for i in range(0, 256):
    sum1 = sum1 + count[i]
    count[i] = sum1

# 计算映射表
map1 = np.zeros(256, np.uint16)
for i in range(0, 256):
    map1[i] = np.uint16(count[i] * 255)

# 映射
for i in range(0, height):
    for j in range(0, width):
        pixel = gray[i, j]
        gray[i, j] = map1[pixel]
cv2.imshow('dst', gray)
cv2.waitKey(0)

运行结果如下:

5-8 彩色直方图均衡化

代码如下:

# 本质:统计每个像素灰度 出现的概率 0-255 p
# 累计概率
# 1 0.2  0.2
# 2 0.3  0.5
# 3 0.1  0.6
# 256
# 100 0.5 255*0.5 = new
# 1 统计每个颜色出现的概率 2 累计概率 1 3 0-255 255*p
# 4 pixel
import cv2
import numpy as np

img = cv2.imread('06.jpg', 1)
cv2.imshow('src', img)

imgInfo = img.shape
height = imgInfo[0]
width = imgInfo[1]

count_b = np.zeros(256, np.float)
count_g = np.zeros(256, np.float)
count_r = np.zeros(256, np.float)
for i in range(0, height):
    for j in range(0, width):
        (b, g, r) = img[i, j]
        index_b = int(b)
        index_g = int(g)
        index_r = int(r)
        count_b[index_b] = count_b[index_b] + 1
        count_g[index_g] = count_g[index_g] + 1
        count_r[index_r] = count_r[index_r] + 1
for i in range(0, 255):
    count_b[i] = count_b[i] / (height * width)
    count_g[i] = count_g[i] / (height * width)
    count_r[i] = count_r[i] / (height * width)
# 计算累计概率
sum_b = float(0)
sum_g = float(0)
sum_r = float(0)
for i in range(0, 256):
    sum_b = sum_b + count_b[i]
    sum_g = sum_g + count_g[i]
    sum_r = sum_r + count_r[i]
    count_b[i] = sum_b
    count_g[i] = sum_g
    count_r[i] = sum_r
# print(count)
# 计算映射表
map_b = np.zeros(256, np.uint16)
map_g = np.zeros(256, np.uint16)
map_r = np.zeros(256, np.uint16)
for i in range(0, 256):
    map_b[i] = np.uint16(count_b[i] * 255)
    map_g[i] = np.uint16(count_g[i] * 255)
    map_r[i] = np.uint16(count_r[i] * 255)
# 映射
dst = np.zeros((height, width, 3), np.uint8)
for i in range(0, height):
    for j in range(0, width):
        (b, g, r) = img[i, j]
        b = map_b[b]
        g = map_g[g]
        r = map_r[r]
        dst[i, j] = (b, g, r)
cv2.imshow('dst', dst)
cv2.waitKey(0)

运行结果如下:

5-9 亮度增强

代码如下:

# p = p+40
import cv2
import numpy as np

img = cv2.imread('07.jpg', 1)
imgInfo = img.shape
height = imgInfo[0]
width = imgInfo[1]
cv2.imshow('src', img)
dst = np.zeros((height, width, 3), np.uint8)
for i in range(0, height):
    for j in range(0, width):
        (b, g, r) = img[i, j]
        bb = int(b) + 40
        gg = int(g) + 40
        rr = int(r) + 40
        if bb > 255:
            bb = 255
        if gg > 255:
            gg = 255
        if rr > 255:
            rr = 255
        dst[i, j] = (bb, gg, rr)
cv2.imshow('dst', dst)
cv2.waitKey(0)

运行结果如下:

5-10 磨皮美白

代码如下:

import cv2
import numpy as np

img = cv2.imread('08.jpg', 1)
imgInfo = img.shape
height = imgInfo[0]
width = imgInfo[1]
cv2.imshow('src', img)
dst = np.zeros((height, width, 3), np.uint8)

for i in range(0, height):
    for j in range(0, width):
        b, g, r = img[i, j]
        bb = int(b * 1.3) + 15
        gg = int(g * 1.2) + 20
        rr = int(r * 1.2) + 10

        if bb > 255:
            bb = 255
        if gg > 255:
            gg = 255

        dst[i, j] = (bb, gg, r)

cv2.imshow('dst', dst)
cv2.waitKey(0)

运行结果如下:

5-11 高斯均值滤波

代码如下:

import cv2
import numpy as np

img = cv2.imread('09.jpg', 1)
cv2.imshow('img', img)

# 方法一:使用OpenCV中的GaussianBlur进行高斯滤波
dst1 = cv2.GaussianBlur(img, (5, 5), 1.5)
cv2.imshow('dst1', dst1)

# 方法二:修改源码记性高斯滤波
imgInfo = img.shape
height = imgInfo[0]
width = imgInfo[1]
dst2 = np.zeros((height, width, 3), np.uint8)
for i in range(3, height - 3):
    for j in range(3, width - 3):
        sum_b = int(0)
        sum_g = int(0)
        sum_r = int(0)
        for m in range(-3, 3):
            for n in range(-3, 3):
                (b, g, r) = img[i + m, j + n]
                sum_b = sum_b + int(b)
                sum_g = sum_g + int(g)
                sum_r = sum_r + int(r)

        b = np.uint8(sum_b / 36)
        g = np.uint8(sum_g / 36)
        r = np.uint8(sum_r / 36)
        dst2[i, j] = (b, g, r)
cv2.imshow('dst2', dst2)
cv2.waitKey(0)

运行结果如下:

5-12 中值滤波

代码如下:

# 中值滤波 3*3
import cv2
import numpy as np

img = cv2.imread('05.jpg', 1)
imgInfo = img.shape
height = imgInfo[0]
width = imgInfo[1]
img = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
cv2.imshow('src', img)
dst = np.zeros((height, width, 3), np.uint8)
collect = np.zeros(9, np.uint8)
for i in range(1, height - 1):
    for j in range(1, width - 1):
        k = 0
        for m in range(-1, 2):
            for n in range(-1, 2):
                gray = img[i + m, j + n]
                collect[k] = gray
                k = k + 1
        # 0 1 2 3 4 5 6 7 8
        #   1
        for k in range(0, 9):
            p1 = collect[k]
            for t in range(k + 1, 9):
                if p1 < collect[t]:
                    mid = collect[t]
                    collect[t] = p1
                    p1 = mid
        dst[i, j] = collect[4]
cv2.imshow('dst', dst)
cv2.waitKey(0)

运行结果如下:

本文版权归趣KUAI排www.SEOguruBlog.com 所有,如有转发请注明来出,竞价开户托管,seo优化请联系QQ→61910465