龙空技术网

Python图像处理丨带你认识图像量化处理及局部马赛克特效

华为云开发者联盟 684

前言:

当前看官们对“opencv kmeans分割”大约比较看重,你们都想要学习一些“opencv kmeans分割”的相关内容。那么小编也在网摘上收集了一些对于“opencv kmeans分割””的相关文章,希望兄弟们能喜欢,看官们一起来了解一下吧!

本文分享自华为云社区《[Python图像处理] 二十.图像量化处理和采样处理及局部马赛克特效-云社区-华为云》,作者: eastmount。

本文主要讲述如何进行图像量化处理和采样处理及局部马赛克特效。

一.图像量化处理

图像通常是自然界景物的客观反映,并以照片形式或视频记录的介质连续保存,获取图像的目标是从感知的数据中产生数字图像,因此需要把连续的图像数据离散化,转换为数字化图像,其工作主要包括两方面——量化和采样。数字化幅度值称为量化,数字化坐标值称为采样。本章主要讲解图像量化和采样处理的概念,并通过Python和OpenCV实现这些功能。

1.1 概述

所谓量化(Quantization),就是将图像像素点对应亮度的连续变化区间转换为单个特定值的过程,即将原始灰度图像的空间坐标幅度值离散化。量化等级越多,图像层次越丰富,灰度分辨率越高,图像的质量也越好;量化等级越少,图像层次欠丰富,灰度分辨率越低,会出现图像轮廓分层的现象,降低了图像的质量。图6-1是将图像的连续灰度值转换为0至255的灰度级的过程。

如果量化等级为2,则将使用两种灰度级表示原始图片的像素(0-255),灰度值小于128的取0,大于等于128的取128;如果量化等级为4,则将使用四种灰度级表示原始图片的像素,新图像将分层为四种颜色,0-64区间取0,64-128区间取64,128-192区间取128,192-255区间取192;依次类推。

图6-2是对比不同量化等级的“Lena”图。其中(a)的量化等级为256,(b)的量化等级为64,(c)的量化等级为16,(d)的量化等级为8,(e)的量化等级为4,(f)的量化等级为2。

1.2 操作

下面讲述Python图像量化处理相关代码操作。其核心流程是建立一张临时图片,接着循环遍历原始图像中所有像素点,判断每个像素点应该属于的量化等级,最后将临时图像显示。下述代码将灰度图像转换为两种量化等级。

# -*- coding: utf-8 -*-import cv2  import numpy as np  import matplotlib.pyplot as plt#读取原始图像img = cv2.imread('lena.png')#获取图像高度和宽度height = img.shape[0]width = img.shape[1]#创建一幅图像new_img = np.zeros((height, width, 3), np.uint8)#图像量化操作 量化等级为2for i in range(height): for j in range(width): for k in range(3): #对应BGR三分量 if img[i, j][k] < 128:                gray = 0 else:                gray = 128 new_img[i, j][k] = np.uint8(gray)#显示图像cv2.imshow("src", img)cv2.imshow("", new_img)#等待显示cv2.waitKey(0)cv2.destroyAllWindows()

其输出结果如图6-3所示,它将灰度图像划分为两种量化等级。

下面的代码分别比较了量化等级为2、4、8的量化处理效果。

# -*- coding: utf-8 -*-import cv2  import numpy as np  import matplotlib.pyplot as plt#读取原始图像img = cv2.imread('lena.png')#获取图像高度和宽度height = img.shape[0]width = img.shape[1]#创建一幅图像new_img1 = np.zeros((height, width, 3), np.uint8)new_img2 = np.zeros((height, width, 3), np.uint8)new_img3 = np.zeros((height, width, 3), np.uint8)#图像量化等级为2的量化处理for i in range(height): for j in range(width): for k in range(3): #对应BGR三分量 if img[i, j][k] < 128:                gray = 0 else:                gray = 128            new_img1[i, j][k] = np.uint8(gray)#图像量化等级为4的量化处理for i in range(height): for j in range(width): for k in range(3): #对应BGR三分量 if img[i, j][k] < 64:                gray = 0 elif img[i, j][k] < 128:                gray = 64 elif img[i, j][k] < 192:                gray = 128 else:                gray = 192            new_img2[i, j][k] = np.uint8(gray)#图像量化等级为8的量化处理for i in range(height): for j in range(width): for k in range(3): #对应BGR三分量 if img[i, j][k] < 32:                gray = 0 elif img[i, j][k] < 64:                gray = 32 elif img[i, j][k] < 96:                gray = 64 elif img[i, j][k] < 128:                gray = 96 elif img[i, j][k] < 160:                gray = 128 elif img[i, j][k] < 192:                gray = 160 elif img[i, j][k] < 224:                gray = 192 else:                gray = 224            new_img3[i, j][k] = np.uint8(gray)#用来正常显示中文标签plt.rcParams['font.sans-serif']=['SimHei']#显示图像titles = [u'(a) 原始图像', u'(b) 量化-L2', u'(c) 量化-L4', u'(d) 量化-L8'] images = [img, new_img1, new_img2, new_img3] for i in xrange(4):  plt.subplot(2,2,i+1), plt.imshow(images[i], 'gray'),  plt.title(titles[i])  plt.xticks([]),plt.yticks([]) plt.show()

输出结果如图6-4所示,该代码调用matplotlib.pyplot库绘制了四幅图像,其中(a)表示原始图像,(b)表示等级为2的量化处理,(c)表示等级为4的量化处理,(d)表示等级为8的量化处理。

1.3 K-Means聚类量化处理

上一小节的量化处理是通过遍历图像中的所有像素点,进行灰度图像的幅度值离散化处理。本小节补充一个基于K-Means聚类算法的量化处理过程,它能够将彩色图像RGB像素点进行颜色分割和颜色量化。更多知识推荐大家学习前一篇文章。

# coding: utf-8import cv2import numpy as npimport matplotlib.pyplot as plt#读取原始图像img = cv2.imread('people.png') #图像二维像素转换为一维data = img.reshape((-1,3))data = np.float32(data)#定义中心 (type,max_iter,epsilon)criteria = (cv2.TERM_CRITERIA_EPS +            cv2.TERM_CRITERIA_MAX_ITER, 10, 1.0)#设置标签flags = cv2.KMEANS_RANDOM_CENTERS#K-Means聚类 聚集成4类compactness, labels, centers = cv2.kmeans(data, 4, None, criteria, 10, flags)#图像转换回uint8二维类型centers = np.uint8(centers)res = centers[labels.flatten()]dst = res.reshape((img.shape))#图像转换为RGB显示img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)dst = cv2.cvtColor(dst, cv2.COLOR_BGR2RGB)#用来正常显示中文标签plt.rcParams['font.sans-serif']=['SimHei']#显示图像titles = [u'原始图像', u'聚类量化 K=4'] images = [img, dst] for i in xrange(2):  plt.subplot(1,2,i+1), plt.imshow(images[i], 'gray'),  plt.title(titles[i])  plt.xticks([]),plt.yticks([]) plt.show()

输出结果如图6-4所示,它通过K-Means聚类算法将彩色人物图像的灰度聚集成四种颜色。

二.图像采样处理2.1 概述

图像采样(Image Sampling)处理是将一幅连续图像在空间上分割成M×N个网格,每个网格用一个亮度值或灰度值来表示,其示意图如图6-5所示。

图像采样的间隔越大,所得图像像素数越少,空间分辨率越低,图像质量越差,甚至出现马赛克效应;相反,图像采样的间隔越小,所得图像像素数越多,空间分辨率越高,图像质量越好,但数据量会相应的增大。图6-6展示了不同采样间隔的“Lena”图。

2.2 操作

下面讲述Python图像采样处理相关代码操作。其核心流程是建立一张临时图片,设置需要采样的区域大小(如16×16),接着循环遍历原始图像中所有像素点,采样区域内的像素点赋值相同(如左上角像素点的灰度值),最终实现图像采样处理。代码是进行16×16采样的过程。

# -*- coding: utf-8 -*-import cv2  import numpy as np  import matplotlib.pyplot as plt#读取原始图像img = cv2.imread('scenery.png')#获取图像高度和宽度height = img.shape[0]width = img.shape[1]#采样转换成16*16区域numHeight = height/16numwidth = width/16#创建一幅图像new_img = np.zeros((height, width, 3), np.uint8)#图像循环采样16*16区域for i in range(16): #获取Y坐标    y = i*numHeight for j in range(16): #获取X坐标        x = j*numwidth #获取填充颜色 左上角像素点        b = img[y, x][0]        g = img[y, x][1]        r = img[y, x][2] #循环设置小区域采样 for n in range(numHeight): for m in range(numwidth): new_img[y+n, x+m][0] = np.uint8(b) new_img[y+n, x+m][1] = np.uint8(g) new_img[y+n, x+m][2] = np.uint8(r)#显示图像cv2.imshow("src", img)cv2.imshow("", new_img)#等待显示cv2.waitKey(0)cv2.destroyAllWindows()

输出结果如下图所示:

同样,可以对彩色图像进行采样处理,下面的代码将彩色风景图像采样处理成8×8的马赛克区域。

# -*- coding: utf-8 -*-import cv2  import numpy as np  import matplotlib.pyplot as plt#读取原始图像img = cv2.imread('scenery.png')#获取图像高度和宽度height = img.shape[0]width = img.shape[1]#采样转换成8*8区域numHeight = height/8numwidth = width/8#创建一幅图像new_img = np.zeros((height, width, 3), np.uint8)#图像循环采样8*8区域for i in range(8): #获取Y坐标    y = i*numHeight for j in range(8): #获取X坐标        x = j*numwidth #获取填充颜色 左上角像素点        b = img[y, x][0]        g = img[y, x][1]        r = img[y, x][2] #循环设置小区域采样 for n in range(numHeight): for m in range(numwidth): new_img[y+n, x+m][0] = np.uint8(b) new_img[y+n, x+m][1] = np.uint8(g) new_img[y+n, x+m][2] = np.uint8(r)#显示图像cv2.imshow("src", img)cv2.imshow("Sampling", new_img)#等待显示cv2.waitKey(0)cv2.destroyAllWindows()

其输出结果如图所示,它将彩色风景图像采样成8×8的区域。

但上述代码存在一个问题,当图像的长度和宽度不能被采样区域整除时,输出图像的最右边和最下边的区域没有被采样处理。这里推荐读者做个求余运算,将不能整除部门的区域也进行采样处理。

2.3 局部马赛克处理

前面讲述的代码是对整幅图像进行采样处理,那么如何对图像的局部区域进行马赛克处理呢?下面的代码就实现了该功能。当鼠标按下时,它能够给鼠标拖动的区域打上马赛克,并按下“s”键保存图像至本地。

# -- coding:utf-8 --import cv2  import numpy as np  import matplotlib.pyplot as plt#读取原始图像im = cv2.imread('people.png', 1)#设置鼠标左键开启en = False#鼠标事件def draw(event, x, y, flags, param): global en #鼠标左键按下开启en值 if event==cv2.EVENT_LBUTTONDOWN: en = True #鼠标左键按下并且移动elif event==cv2.EVENT_MOUSEMOVE and flags==cv2.EVENT_LBUTTONDOWN: #调用函数打马赛克 if en: drawMask(y,x) #鼠标左键弹起结束操作 elif event==cv2.EVENT_LBUTTONUP: en = False#图像局部采样操作 def drawMask(x, y, size=10): #size*size采样处理    m = x / size * size      n = y / size * size print m, n #10*10区域设置为同一像素值 for i in range(size): for j in range(size): im[m+i][n+j] = im[m][n]#打开对话框cv2.namedWindow('image')#调用draw函数设置鼠标操作cv2.setMouseCallback('image', draw)#循环处理while(1):    cv2.imshow('image', im) #按ESC键退出 if cv2.waitKey(10)&0xFF==27: break #按s键保存图片 elif cv2.waitKey(10)&0xFF==115:        cv2.imwrite('sava.png', im)#退出窗口cv2.destroyAllWindows()

其输出结果如图所示,它将人物的脸部进行马赛克处理。

点击下方,第一时间了解华为云新鲜技术~

华为云博客_大数据博客_AI博客_云计算博客_开发者中心-华为云

标签: #opencv kmeans分割