一、灰度处理
import cv2
img0 = cv2.imread('image0.jpg', 0)
img1 = cv2.imread('image0.jpg', 1)
print(img0.shape)
print(img1.shape)
cv2.imshow('src', img0)
cv2.waitKey(0)
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/61f55b9e2bd1de9f3616af06d562790b.png)
- 使用openCV的cvtColor方法实现:cvtColor实现颜色空间的转换
import cv2
img = cv2.imread('image0.jpg', 1)
dst = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
cv2.imshow('dst', dst)
cv2.waitKey(0)
- 利用R=G=B的方式实现:使用(R+G+B)/ 3 赋值给像素点
import cv2
import numpy as np
img = cv2.imread('image0.jpg', 1)
imgInfo = img.shape
height = imgInfo[0]
width = imgInfo[1]
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]
gray = (int(b) + int(g) + int(r)) / 3
dst[i, j] = np.uint8(gray)
cv2.imshow('dst', dst)
cv2.waitKey(0)
- 使用心理学公式:r * 0.299 + g * 0.587 + b * 0.114
import cv2
import numpy as np
img = cv2.imread('image0.jpg', 1)
imgInfo = img.shape
height = imgInfo[0]
width = imgInfo[1]
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 = int(b)
g = int(g)
r = int(r)
gray = r * 0.299 + g * 0.587 + b * 0.114
dst[i, j] = np.uint8(gray)
cv2.imshow('dst', dst)
cv2.waitKey(0)
- 算法优化:浮点数据转换成定点数据;乘除转换成位移计算
- 这里的系数是按乘以4计算了,如果希望精度更快,可以乘100,1000。。。。。
import cv2
import numpy as np
img = cv2.imread('image0.jpg', 1)
imgInfo = img.shape
height = imgInfo[0]
width = imgInfo[1]
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 = int(b)
g = int(g)
r = int(r)
gray = (r + (g << 1) + b) >> 2
dst[i, j] = np.uint8(gray)
cv2.imshow('dst', dst)
cv2.waitKey(0)
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/934ceebce17b92edb6d6c34473ecb17d.png)
二、颜色反转
import cv2
import numpy as np
img = cv2.imread('image0.jpg', 1)
imgInfo = img.shape
height = imgInfo[0]
width = imgInfo[1]
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
dst = np.zeros((height, width, 1), np.uint8)
for i in range(0, height):
for j in range(0, width):
grayPixel = gray[i, j]
dst[i, j] = 255 - grayPixel
cv2.imshow('dst', dst)
cv2.waitKey(0)
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/c6b62a78604ab408c9fe05221790c12a.png)
import cv2
import numpy as np
img = cv2.imread('image0.jpg', 1)
imgInfo = img.shape
height = imgInfo[0]
width = imgInfo[1]
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]
dst[i, j] = (255 - b, 255 - g, 255 - r)
cv2.imshow('dst', dst)
cv2.waitKey(0)
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/dfbba8aeb37cda0b8a4d3312a42998ef.png)
三、马赛克
- 图片实现马赛克的原理:将一片区局域中的所有的像素保持一致
- 例如:我们想给一个10 * 10的区域打上马赛克
- 那么我们取到10*10中左上角点的像素值,替换掉10 * 10的100个像素点
- 这样就实现了马赛克效果
import cv2
img = cv2.imread('image0.jpg', 1)
imgInfo = img.shape
height = imgInfo[0]
width = imgInfo[1]
for m in range(100, 300):
for n in range(100, 200):
if m % 10 == 0 and n % 10 == 0:
for i in range(0, 10):
for j in range(0, 10):
(b, g, r) = img[m, n]
img[i + m, j + n] = (b, g, r)
cv2.imshow('dst', img)
cv2.waitKey(0)
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/404701d7edd62f0519c6b0fbdc9b7249.png)
四、毛玻璃
- 毛玻璃的实现原理:
- 马赛克效果我们使用的是左上角的像素点来替换掉其他像素点
- 而毛玻璃是使用随机的像素点来替换掉当前的像素点
import cv2
import numpy as np
import random
img = cv2.imread('image0.jpg', 1)
imgInfo = img.shape
height = imgInfo[0]
width = imgInfo[1]
dst = np.zeros((height, width, 3), np.uint8)
mm = 8
for m in range(0, height - mm):
for n in range(0, width - mm):
index = int(random.random() * 8)
(b, g, r) = img[m + index, n + index]
dst[m, n] = (b, g, r)
cv2.imshow('dst', dst)
cv2.waitKey(0)
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/b9162373c6c475774d37f542ed83091e.png)
五、图片融合
- 2张图片融合的计算公式:dst = src1a+src2(1-a),其中a指的是alpha系数
import cv2
img0 = cv2.imread('image0.jpg', 1)
img1 = cv2.imread('image1.jpg', 1)
imgInfo = img0.shape
height = imgInfo[0]
width = imgInfo[1]
roiH = int(height / 2)
roiW = int(width / 2)
img0ROI = img0[0:roiH, 0:roiW]
img1ROI = img1[0:roiH, 0:roiW]
dst = cv2.addWeighted(img0ROI, 0.5, img1ROI, 0.5, 0)
cv2.imshow('dst', dst)
cv2.waitKey(0)
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/43caa4ebea98f2fd00d1c9658d9db9ed.png)
六、边缘检测与浮雕效果
1 - 边缘检测
- 什么是边缘检测:边缘检测的效果有点类似素描,边缘检测的实质是图像的卷积计算
- openCV的API方式实现边缘检测的步骤:
import cv2
img = cv2.imread('image0.jpg', 1)
imgInfo = img.shape
height = imgInfo[0]
width = imgInfo[1]
cv2.imshow('src', img)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
imgG = cv2.GaussianBlur(gray, (3, 3), 0)
dst = cv2.Canny(img, 50, 50)
cv2.imshow('dst', dst)
cv2.waitKey(0)
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/468615f069682ae73325ea8c1af9398a.png)
- 源码形式实现边缘检测:sobel算法实现,这里会涉及到如下几个概念
- sobel算法的算子模板:水平方向、垂直方向
水平方向 垂直方向
[1 2 1 [ 1 0 -1
0 0 0 2 0 -2
-1 -2 -1 ] 1 0 -1 ]
- 图片卷积:假设1张图片中的4个像素点为[1 2 3 4],当前的模板是[a b c d],那么卷积的结果:a1+b2+c3+d4 = dst
- a:竖直方向上的梯度 -> 水平方向上的算子与图片卷积的结果
- b:水平方向上的梯度 -> 垂直方向上的算子与图片卷积的结果
- f:阀值,f = sqrt(a * a + b * b)
- th:判决门限
- 阀值判决:f > th 是边缘,否则是非边缘
import cv2
import numpy as np
import math
img = cv2.imread('image0.jpg', 1)
imgInfo = img.shape
height = imgInfo[0]
width = imgInfo[1]
cv2.imshow('src', img)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
dst = np.zeros((height, width, 1), np.uint8)
for i in range(0, height - 2):
for j in range(0, width - 2):
gy = gray[i, j] * 1 + gray[i, j + 1] * 2 + gray[i, j + 2] * 1 - gray[i + 2, j] * 1 - gray[i + 2, j + 1] * 2 - \
gray[i + 2, j + 2] * 1
gx = gray[i, j] + gray[i + 1, j] * 2 + gray[i + 2, j] - gray[i, j + 2] - gray[i + 1, j + 2] * 2 - gray[
i + 2, j + 2]
grad = math.sqrt(gx * gx + gy * gy)
if grad > 50:
dst[i, j] = 255
else:
dst[i, j] = 0
cv2.imshow('dst', dst)
cv2.waitKey(0)
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/5b44ea05eb7e992e423d35dab01d1dc3.png)
2 - 浮雕效果
- 浮雕效果计算公式:每一个新的像素值等于相邻像素的像素值之差加上一个恒定值(比如150)
- newP = gray0 - gray1 + 150
- 这里加上150是为了增强图片的浮雕灰度等级
- 相邻像素相减是为了突出灰度的突片及边缘特征
import cv2
import numpy as np
img = cv2.imread('image0.jpg', 1)
imgInfo = img.shape
height = imgInfo[0]
width = imgInfo[1]
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
dst = np.zeros((height, width, 1), np.uint8)
for i in range(0, height):
for j in range(0, width - 1):
grayP0 = int(gray[i, j])
grayP1 = int(gray[i, j + 1])
newP = grayP0 - grayP1 + 150
if newP > 255:
newP = 255
if newP < 0:
newP = 0
dst[i, j] = newP
cv2.imshow('dst', dst)
cv2.waitKey(0)
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/77fa5ec8785cb139d86d985842042954.png)
七、颜色映射
- 颜色映射最简单的实现方式:
- 做一个很大的查找表,根据原始图像的rgb值根据查找表查找一组新的rgb,用新的rgb代替原来像素值
- 也可以用一些简单的公式完成颜色映射,利用公式的方法可能无法表示一些更为复杂的效果
- 案例:蓝色与绿色增强
import cv2
import numpy as np
img = cv2.imread('image0.jpg', 1)
cv2.imshow('src', img)
imgInfo = img.shape
height = imgInfo[0]
width = imgInfo[1]
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 = b * 1.5
g = g * 1.3
if b > 255:
b = 255
if g > 255:
g = 255
dst[i, j] = (b, g, r)
cv2.imshow('dst', dst)
cv2.waitKey(0)
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/ff7a412a2217793716194aa485e62012.png)
八、油画效果
- 油画效果实现步骤
- ①.gray 灰度化
- ②.将图片分割为若干个小方块。统计这些小方块中每个像素的灰度值,比如7 * 7 ,10 * 10
- ③.将0-255划分段,并将第二步的映射到对应段范围中:如划分4个段,每个段有64个等级。0-63 第1段;64-127第2段
- ④.例如:这时有一个像素点.灰度值是10,那么他就在0-63这个点
- 找到每个方块中灰度等级最多的所有像素,count 并求取这些像素的均值
- 用统计出来的平均值,替代原来的像素值
import cv2
import numpy as np
img = cv2.imread('image0.jpg', 1)
cv2.imshow('src', img)
imgInfo = img.shape
height = imgInfo[0]
width = imgInfo[1]
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
dst = np.zeros((height, width, 3), np.uint8)
for i in range(4, height - 4):
for j in range(4, width - 4):
array1 = np.zeros(8, np.uint8)
for m in range(-4, 4):
for n in range(-4, 4):
p1 = int(gray[i + m, j + n] / 32)
array1[p1] = array1[p1] + 1
currentMax = array1[0]
l = 0
for k in range(0, 8):
if currentMax < array1[k]:
currentMax = array1[k]
l = k
for m in range(-4, 4):
for n in range(-4, 4):
if gray[i + m, j + n] >= (l * 32) and gray[i + m, j + n] <= ((l + 1) * 32):
(b, g, r) = img[i + m, j + n]
dst[i, j] = (b, g, r)
cv2.imshow('dst', dst)
cv2.waitKey(0)
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/c2a3d1178c14397c3d4583974f855af8.png)