一.图像特效介绍
1.灰度处理:彩色图片灰度化
- 对于彩色图片有三个颜色通道:RGB
- 对于灰度图片如果也是三个颜色通道,则RGB值是相等的
2.底板效果(灰度)
- 彩色底板是通过当前RGB取反得到的
3.马赛克效果
- 将周边的像素点用同一个像素点取代
4.毛玻璃效果
- 将像素用随机像素来替代
5.颜色映射
- 利用RBG表进行颜色统一映射
6.边缘检测
- 卷积运算
7.浮雕效果
- 在边缘检测上添加底板
二.图像灰度处理
1.开发思路
- 方法1:使用imread方法实现颜色直接转换处理
- 方法2:使用cvtColor方法实现颜色转换
- 方法3:源码实现图像灰度处理
灰度图像R=G=B
- 方法4:心理学计算公式实现图像灰度处理
gray = r*0.299+g*0.587+b*0.114
2.实例代码
-
方法1实例代码
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)
-
方法2实例代码
import cv2 img = cv2.imread('image0.png',1) dst = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)#完成颜色空间转换,参数:原始待转换图片的数据,颜色转换的方式 cv2.imshow('src',dst) cv2.waitKey(0)
-
方法3实现代码
import cv2 import numpy as np img = cv2.imread('image0.png',1) imgInfo = img.shape height = imgInfo[0] width = imgInfo[1] #RGB R=G=B Gray (R+G+B)/3 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)
-
方法4实现代码
import cv2 import numpy as np img = cv2.imread('image0.png',1) imgInfo = img.shape height = imgInfo[0] width = imgInfo[1] #RGB R=G=B Gray (R+G+B)/3 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)
3.灰度算法优化
- 灰度图像是所有图像特效的基础
- 灰度图像强调算法的实时性
- 算法优化原则:定点运算时间 < 浮点运算时间 移位运算时间 < 加减运算时间 < 乘除运算时间
- 优化
r*0.299+g*0.587+b*0.114
公式- 浮点转定点
int(x)
gray = (r*1+g*2+b*1)/4
相当于先左移两位,再右移两位【肯定有误差的】- 进一步优化
gray = (r+(g<<1)+b)>>2
,将浮点运算变成定点运算后,将乘除运算编程移位运算
- 浮点转定点
4.实例代码
import cv2
import numpy as np
img = cv2.imread('image0.png',1)
imgInfo = img.shape
height = imgInfo[0]
width = imgInfo[1]
#RGB R=G=B Gray (R+G+B)/3
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)
三.颜色反转
1.开发思路
- 灰度图片颜色反转:对于灰度图片取值范围是0-255,颜色反转是255-当前灰度值
- 彩色图片颜色反转:对于RGB有3个通道,每一个像素值都是255-当前的像素值(如R=255-R,G=255-G,B=255-B)
2.实例代码
-
灰度图片颜色反转实例代码
import cv2 import numpy as np img = cv2.imread('image0.png',1) imgInfo = img.shape height = imgInfo[0] width = imgInfo[1] gary = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) dst = np.zeros((height,width,3),np.uint8)#其中3表示的是一个像素由几种颜色构成,彩色为3,灰色为1 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)
-
彩色图片颜色反转实例代码
import cv2 import numpy as np img = cv2.imread('image0.png',1) imgInfo = img.shape height = imgInfo[0] width = imgInfo[1] dst = np.zeros((height,width,3),np.uint8)#其中3表示的是一个像素由几种颜色构成,彩色为3,灰色为1 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)
四.马赛克效果
1.开发设计
- 马赛克效果的窗体范围:如行100-300,列100-200
- 每一个马赛克都有一个小窗口,有矩形的马赛克(10*10),也有圆形的马赛克【本例中使用矩形的马赛克】
- 使用10*10像素块中左上角的像素替换像素块中所有的像素
2.实例代码
import cv2
import numpy as np
img = cv2.imread('image0.png',1)
imgInfo = img.shape
height = imgInfo[0]
width = imgInfo[1]
for m in range(100,300):
for n in range(100,200):
#选中一个元素,替换调10*10中所有的像素点,让10*10中保持一致
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)
五.毛玻璃
1.开发设计
- 毛玻璃的思想与马赛克一致,但不是使用固定像素进行像素的替换,而是使用随机的像素替换像素块中的内容
2.实例代码
import cv2
import numpy as np
import random
img = cv2.imread('image0.png',1)
imgInfo = img.shape
height = imgInfo[0]
width = imgInfo[1]
dst = np.zeros((height,width,3),np.uint8)
mm = 8#设置随机数的范围在水平和垂直上均为8,即8*8的像素块中取随机像素
for m in range(0,height-mm):
for n in range(0,width-mm):
index = int(random.random()*8)#random.random()生成的随机数是0-1,*8后,随机数的范围就是0-8
(b,g,r) = img[m+index,n+index]
dst[m,n] = (b,g,r)
cv2.imshow('dst',dst)
cv2.waitKey(0)
3.注意事项
- 最右侧和最下侧都会有8个黑色区域,是因为垂直和水平方向各减去了8,默认填充为0,即为黑色区域
六.图片融合
1.开发设计
目标图片=src1*a系数+src2*(1-a系数)
2.实例代码
import cv2
import numpy as np
img0 = cv2.imread('image0.png',1)#读取图片1
img1 = cv2.imread('image1.png',1)#读取图片2
imgInfo = img0.shape#因为图片1和2的宽高一样,通过此处获得图片的宽高信息
height = imgInfo[0]
width = imgInfo[1]
#ROI感兴趣范围(即将原图扣除一部分,此部分的宽度为源高度的1/2,高度为源高度的1/2)
roiH = int(height/2)
roiW = int(width/2)
img0ROI = img0[0:roiH,0:roiW]#第一个图片感兴趣区域矩阵
img1ROI = img1[0:roiH,0:roiW]#第二个图片感兴趣区域矩阵
#dst
dst = np.zeros((roiH,roiW,3),np.uint8)
dst = cv2.addWeighted(img0ROI,0.5,img1ROI,0.5,0)#第一个图片的权重和第二个图片的权重都是0.5。实现的是权重的计算:目标图片=src1*a系数+src2*(1-a系数)。
#参数1:src1,参数2:src1权重,参数3:src2,参数4:src2权重
cv2.imshow('dst',dst)
cv2.waitKey(0)
七.边缘检测
1.开发设计
- 完成图像的灰度处理,基于灰度图像的(将彩色图片转换成灰度图片)
- 执行高斯滤波,去除噪声的干扰
- 调用opencv中的canny方法实现边缘检测
2.实例代码
import cv2
import numpy as np
import random
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)#实现高斯滤波,参数1:灰度图像数据;参数2:模板大小
dst = cv2.Canny(img,50,50)#参数1:传递图片的数据,参数2:门限值(如果图片经过卷积之后的值大于这个门限,则默认为边缘点,否则则视为非边缘点)
cv2.imshow('dst',dst)
cv2.waitKey(0)
3.源码实现sobel算法
-
算法原理
-
算子模板【分水平方向和竖直方向】
#矩阵1 [1 2 1 0 0 0 -1 -2 -1] #矩阵2 [1 0 -1 2 0 -2 1 0 -1]
-
图片卷积【不是矩阵行列式计算,是矩阵中的数值对应相乘得到的结果】
#eg #源模板[1 2 3 4] #算子模板[a b c d] #结果a*1+b*2+c*3+d*4 = dst 结果称之为梯度,有水平方向和竖直方向两种情况
-
阈值判决
#算子模板1(竖直方向上的算子)与垂直方向上的图片进行卷积之后得到的结果为a,称为竖直上的梯度 #算子模板2(水平方向上的算子)与水平方向上的图片进行卷积之后得到的结果为b,称为水平上的梯度 #f值为sqrt(a*a+b*b),与门限进行判决,如果>判决门限则为边缘;如果<判决门限则为非边缘
-
-
实例代码
import cv2 import numpy as np import math img = cv2.imread('image1.jpg',1)#读取图片1 imgInfo = img.shape#因为图片1和2的宽高一样,通过此处获得图片的宽高信息 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):#卷积运算的时候会从左上角[1,1]的位置开始,单位是3*3,所以需要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]*1-gray[i,j+2]*1+gray[i+1,j]*2-gray[i+1,j+2]*2+gray[i+2,j]*1-gray[i+2,j+2]*1 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)
八.浮雕效果
1.开发设计
- 浮雕效果也是计算梯度
- 浮雕效果的计算公式
新像素值=gray0-gray1+150
,相邻像素之差加上固定值
- 浮雕效果的计算公式
2.实例代码
import cv2
import numpy as np
img = cv2.imread('image1.jpg',1)
imgInfo = img.shape
height = imgInfo[0]
width = imgInfo[1]
cv2.imshow('src',img)
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
#newP = gray0-gray1+150
dst = np.zeros((height,width,1),np.uint8)
for i in range(0,height):
for j in range(0,width-1):
grapP0 = 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)
九.颜色映射
1.开发思路
- 通过查找表将原始RGB值替换成新的RGB值
- 增加蓝色系的模拟变换公式:
b=b*1.5,g=g*1.3
2.实例代码
import cv2
import numpy as np
img = cv2.imread('image1.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]
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)
十.油画特效
1.开发思路
- 完成彩色图片到灰度图片的转换
- 将图片分割为若干个小方块,统计每个小方块中像素的灰度值
- 将0-255的灰度值划分为几个等级,并把第二部处理的结果映射到这个范围内
- 找到每个方块中灰度等级最多的像素(灰度段中像素的个数统计),并求取像素的均值
- 用统计出来的平均值替换原来的像素值
2.实例代码
import cv2
import numpy as np
img = cv2.imread('image1.jpg',1)
cv2.imshow('src',img)
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,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]#array1中哪一个等级段获取的像素值最多
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)
十一.线段绘制
1.开发思路
- 绘制空白模板
- 使用
cv2.line()
绘制线段- 参数1:目标图片数据
- 参数2:线段起始位置
- 参数3:线段终止位置
- 参数4:当前颜色
- 参数5:线条宽度
- 参数6:线条类型
2.实例代码
import cv2
import numpy as np
newImageInfo = (500,500,3)#(宽,高,彩色RGB)
dst = np.zeros(newImageInfo,np.uint8)
#绘制线段
cv2.line(dst,(100,100),(400,400),(0,0,255))#参数1:目标图片数据;参数2:线段起始位置;参数3:线段终止位置;参数4:当前颜色
cv2.line(dst,(100,200),(400,200),(0,255,255),20)#参数5:线条宽度
cv2.line(dst,(100,300),(400,300),(0,255,0),20,cv2.LINE_AA)#参数6:线条类型,cv2.LINE_AA比没有设置该类型的边线更光滑;额
#绘制三角形(即闭合的三条线段)
cv2.line(dst,(200,150),(50,250),(25,100,255))
cv2.line(dst,(50,250),(400,380),(25,100,255))
cv2.line(dst,(400,380),(200,150),(25,100,255))
cv2.imshow('dst',dst)
cv2.waitKey(0)
十二.矩形圆形任意多边形绘制
1.开发思路
- 绘制矩形
cv2.rectangle()
- 参数1:目标图片;参数2:左上角坐标;参数3:右下角坐标;参数4:颜色填充;参数5:表示内容是否要填充,-1表示需要填充,大于0则表示线条宽度
- 绘制圆形
cv2.cicle()
- 参数1:目标图片;参数2:表明圆心;参数3:半径;参数4:表示内容是否要填充,-1表示需要填充,大于0则表示线条宽度
- 绘制椭圆形
cv2.ellipse()
- 参数1:目标图片;参数2:表明圆心;参数3:表明轴的长度(长轴、短轴);参数4:偏转角度;参数5:圆弧起始角度;参数6:圆弧终止角度;参数7:颜色填充;参数8:表示内容是否要填充,-1表示需要填充,大于0则表示线条宽度 #绘制任意多边形
2.实例代码
import cv2
import numpy as np
newImageInfo = (500,500,3)
dst = np.zeros(newImageInfo,np.uint8)
#绘制矩形
cv2.rectangle(dst,(50,100),(200,300),(255,0,0),-1)#参数1:目标图片;参数2:左上角坐标;参数3:右下角坐标;参数4:颜色填充;参数5:表示内容是否要填充,-1表示需要填充,大于0则表示线条宽度
#绘制圆形
cv2.circle(dst,(250,250),(50),(0,255,0),2)#参数1:目标图片;参数2:表明圆心;参数3:半径;参数4:表示内容是否要填充,-1表示需要填充,大于0则表示线条宽度
#绘制椭圆形
cv2.ellipse(dst,(256,256),(150,100),0,0,180,(255,255,0),-1)#参数1:目标图片;参数2:表明圆心;参数3:表明轴的长度(长轴、短轴);参数4:偏转角度;参数5:圆弧起始角度;参数6:圆弧终止角度;参数7:颜色填充;参数8:表示内容是否要填充,-1表示需要填充,大于0则表示线条宽度
#绘制任意多边形
points = np.array([[150,50],[140,140],[200,170],[250,250],[150,50]],np.int32)
points = points.reshape((-1,1,2))#实现维度转换
cv2.polylines(dst,[points],True,(0,255,255))
cv2.imshow('dst',dst)
cv2.waitKey(0)
十三.文字图片绘制
1.思路设计
- 绘制文字
- 使用
cv2.putText()
绘制文字
- 使用
- 绘制图片
- 使用
cv2.resize(源图片,(宽,高))
重置图片大小
- 使用
2.实例代码
- 绘制文字
import cv2
import numpy as np
img = cv2.imread('image0.png',1)
font = cv2.FONT_HERSHEY_SIMPLEX#定义字体
cv2.rectangle(img,(150,100),(300,200),(0,255,0),3)
cv2.putText(img,'this is flow',(100,200),font,1,(200,100,255),2,cv2.LINE_4)#参数1:目标图片;参数2:文字内容;参数3:写入的坐标;参数4和参数5:字体和字体大小;参数6:颜色;参数7:粗细信息;参数8:线条类型
cv2.imshow('dst',img)
cv2.waitKey(0)
- 绘制图片
import cv2
img = cv2.imread('image0.png',1)
height = int(img.shape[0]*0.2)
width = int(img.shape[1]*0.2)
imgResize = cv2.resize(img,(width,height))#重置图片宽高得到新矩阵
for i in range(0,height):
for j in range(0,width):
img[i+50,j+100] = imgResize[i,j]
cv2.imshow('dst',img)
cv2.waitKey(0)