OpenCv基础(二)

OpenCv基础(二)


三、图像运算和基本变换

  • OpenCv用mat这种数据结构来表示图片

  • 但在python中,把mat转化为了numpy的ndarray数据格式

  • ndarray数据格式的主要属性:size,shape,dtype

1.1 拷贝

  • 深拷贝img.copy、浅拷贝img.view
import cv2
import numpy as np

img = cv2.imread('../my_work/01.png')
# 浅拷贝
img2 = img.view()
# 深拷贝
img3 = img.copy()

img[10:100,10:100] = [0,0,255]
cv2.imshow('img',np.hstack((img,img2,img3)))	# 横着将几张图片拼接在一起
# cv2.imshow('img',np.vstack((img,img2,img3)))	# # 竖着将几张图片拼接在一起
cv2.waitKey(0)
cv2.destroyAllWindows()

1.2 图像的分割与融合

  • split(img):
    • img:待分割图像
  • merge(mv):
    • mv:合并图像数组
import cv2
import numpy as np

img = np.zeros((200,200,3),np.uint8)

# 分割通道,分成rgb三个通道
b,g,r = cv2.split(img)
# 修改指定通道的部分区域颜色
b[10:100,10:100] = 255
g[10:100,10:100] = 255
# 再合并通道
img2 = cv2.merge((b,g,r))

cv2.imshow("img",np.hstack((img,img2)))
cv2.waitKey(0)
cv2.destroyAllWindows()

1.3 绘制图形

  • 绘制直线:cv2.line(img,pt1,pt2,color,thickness,lineType,shift)

    • img:绘制在img图像上
    • pt1:起始点
    • pt2:终止点
    • color:线条颜色
    • thickness:线条粗细,值 = -1时表示填充
    • lineType:线条类型
    • shift:缩放参数
  • 绘制矩形框:cv2.rectangle()参数同上

  • 绘制圆形:cv2.circle(img,center,radius,color[,thickness,lineType,shift])

    • center:中心点
    • radius:半径
  • 绘制椭圆:cv2.ellipse(img,center,axes,angle,startAngle,endAngle.....)

    • axes:长轴及短轴的一半
    • angle:椭圆旋转的角度
    • startAngle:绘制椭圆起始角度
    • endAngle:绘制椭圆终止角度
  • 多边形:cv2.polylines(img,pts,isClosed,color,thickness)

    • pts:为多边形的点集,必须为int32类型
    • isClosed:是否闭合,值为bool类型
  • 填充多边形:cv2.fillPoly(img,pts,color,thickness)

  • 绘制文本:cv2.putText(img,str,org,fontFace,fontScale,color)

    • str:绘制的文字
    • org:文字起始坐标
    • fontFace:文字格式
    • fontScale:文字大小

代码示例:

import cv2
import numpy as np

img = np.zeros((640,480,3),np.uint8)
# 直线
cv2.line(img,(10,20),(300,400),(0,0,255),5,4)
cv2.line(img,(80,100),(380,480),(0,0,255),5,16)     # 有锯齿状

img2 = np.zeros((640,480,3),np.uint8)
# 矩形
cv2.rectangle(img2,(10,20),(250,460),(0,255,0),5,4)
# 圆
cv2.circle(img2,(240,320),150,(0,255,0),4)

# 椭圆
cv2.ellipse(img2,(240,320),(100,50),0,0,360,[0,0,255])

# 多边形
# pts多边形的点集,必须是int32位
pts = np.array([[(300,10),(150,100),(50,100)]],np.int32)
cv2.polylines(img2,pts,True,(0,0,255),4)

# 填充多边形
cv2.fillPoly(img2,pts,(0,0,255),4)

# 绘制文本,opencv不能绘制中文字体,可以使用pillow包
cv2.putText(img2,'love',(100,120),cv2.FONT_HERSHEY_COMPLEX,3,(0,0,255))


cv2.imshow('draw2',img2)
cv2.imshow('draw',img)
cv2.waitKey(0)
cv2.destroyAllWindows()
  • 使用pillow绘制中文
from PIL import ImageFont,ImageDraw,Image
img = np.full((500,500,3),fill_value=255,dtype=np.uint8)
font = ImageFont.truetype('下载的字体格式路径')
img_pil = Image.fromarray(img)

draw = ImageDraw.Draw(img_pil)
draw.text((100,250),"我爱你",font=font,fill=(0,255,0,0))
img = np.array(img_pil)

cv2.imshow('img',img)
cv2.waitKey(0)
cv2.destroyAllWindows()

1.4 图像的基本运算

  • 加法:cv2.add(img1,img2),像素相加超过255,会变成255,也就是白色
    • 图片还能与单个数字进行运算,每个与100进行加法运算,超出255会被截断,相当于%255
  • 减法:cv2.subtract(img1,img2),减完小于0,变为0
  • 乘法:cv2.multiply(img1,img2),超过255,会变成255
  • 除法:cv2.divide(img1,img2),小于0,变为0
import cv2

img1 = cv2.imread('../my_work/01.png')
img2 = cv2.imread('../my_work/02.png')

# 将尺寸变为一致
new_img1 = cv2.resize(img1,(img2.shape[:-1][::-1]))

# 加法,两个图片的尺寸相同,维数相同
img_add = cv2.add(img1,img2)    # 像素相加超过255,会变成255,也就是白色

# 图片还能与单个数字进行运算,每个与100进行加法运算,超出255会被截断,相当于%255
img3 = img2+100

# 减法,减完小于0,变为0
img4 = cv2.subtract(new_img1,img2)

# 乘法
img5 = cv2.multiply(img1,img1)

# 除法
img6 = cv2.divide(img1,img2)

cv2.imshow('img1_img2',cv2.hconcat((new_img1,img2)))
cv2.imshow('add',img_add)
cv2.imshow('img+n',img3)
cv2.imshow('subtract',img4)
cv2.imshow('img1*img2',img5)
cv2.imshow('img1/img2',img6)

cv2.waitKey()
cv2.destroyAllWindows()

1.5 图像的加法融合

  • 相当于拿图片做了线性运算,new_img = img1*w1 + img2*w2 + bias
    • w1、w2分别为img1和img2所占权重,bias为常数偏置
import cv2
import numpy as np

# 图像融合相当于拿图片做了线性运算,new_img = img1*w1 + img2*w2 + bias
img1 = cv2.imread('../my_work/01.png')
img2 = cv2.imread('../my_work/02.png')
# 将尺寸变为一致
new_img1 = cv2.resize(img1,(img2.shape[:-1][::-1]))

concat = cv2.addWeighted(new_img1,1.2,img2,0.5,-100)

cv2.imshow('img1_img2',cv2.hconcat((new_img1,img2)))
cv2.imshow('concat',concat)

cv2.waitKey()
cv2.destroyAllWindows()

1.6 位运算

  • OpenCv中的逻辑运算—与或非、异或

    • 也就是对应位置元素进行与或非、异或;即对应像素的灰度值转化为二进制进行位运算,再转化为灰度值
    • 0反过来就是255
  • 非运算:相当于255-img

    • cv2.bitwise_and(img1,img2)
  • 或运算:

    • cv2.bitwise_or(img1,img2)
  • 异或运算:

    • cv2.bitwise_xor(img1,img2)
import cv2
import numpy as np

img1 = cv2.imread('../my_work/01.png')
img2 = cv2.imread('../my_work/02.png')

# 非运算,相当于255-img
img1_not = cv2.bitwise_not(img1)

# 与运算,形状要求相同
img1_and_img2 = cv2.bitwise_and(img1,img2)
print(img1[:2,:2])
print(img2[:2,:2])
print(img1_and_img2[:2,:2])

# 或运算
img1_or_img2 = cv2.bitwise_or(img1,img2)

# 异或运算
img1_xor_img2 = cv2.bitwise_xor(img1,img2)

cv2.imshow('not',np.hstack((img1,img1_not)))
cv2.imshow('and',np.hstack((img1,img1_and_img2,img2)))
cv2.imshow('or',np.hstack((img1,img1_or_img2,img2)))
cv2.imshow('xor',np.hstack((img1,img1_xor_img2,img2)))
cv2.waitKey()
cv2.destroyAllWindows()

1.7 resize操作

  • cv2.resize(src,dsize[,dst[,fx,[,fy[,interpolation]]]])
    • src:要缩放的图片
    • dsize:缩放之后的大小,元组和列表表示均可,先宽后高(w,h)
    • dst:可选参数,缩放之后的输出图片
    • fx,fy:x轴和y轴的缩放比,即宽度和高度的缩放比
    • interpolation:插值算法,主要为:
      • INTER_NEAREST,邻近插值,速度快、效果差
      • INTER_LINEAR,双线性插值,默认,需要用原图4个点
      • INTER_CUBIC,三次插值,需要用原图16个点
      • INTER_AREA,区域插值,效果最好、计算时间长
import cv2
import numpy as np

# resize(src,dsize[,dst[,fx,[,fy[,interpolation]]]])
img1 = cv2.imread('../my_work/01.png')
img2 = cv2.imread('../my_work/02.png')

# resize是先宽后高
img1_new = cv2.resize(img1,(img2.shape[:-1][::-1]))
print(img2.shape)
print(img2.shape[:-1])
print(img2.shape[:-1][::-1])

cv2.imshow('img1_new',cv2.hconcat((img1_new,img1)))
cv2.waitKey()
cv2.destroyAllWindows()

1.8 图像的旋转

  • 翻转cv2.flip(src,flipCode)

    • flipCode = 0 表示上下翻转
    • flipCode > 0 表示左右翻转
    • flipCode < 0 表示上下左右翻转
  • 旋转cv2.rotate(src,rotateCode)

    • rotateCode = cv2.ROTATE_90_CLOCKWISE 表示90°顺时针旋转
    • rotateCode = cv2.ROTATE_180 表示180°顺时针旋转
    • rotateCode = cv2.ROTATE_90_COUNTERCLOCKWISE 表示90°逆时针旋转
import cv2

img1 = cv2.imread('../my_work/01.png')
img2 = cv2.imread('../my_work/02.png')

img1_new = cv2.flip(img1,0)
img2_new = cv2.rotate(img2,cv2.ROTATE_90_CLOCKWISE)

cv2.imshow('img1_flip',cv2.hconcat((img1_new,img1)))
# 旋转90度后宽高不一致
cv2.imshow('img2_rotate',img2_new)
cv2.imshow('img2',img2)

cv2.waitKey()
cv2.destroyAllWindows()

1.9 图像的仿射变换—图像平移

  • 仿射变换是图像旋转、缩放、平移的总称。具体做法是通过一个变换矩阵和原图片进行计算,得到新的坐标,完成变换,所以仿射变换的关键是变换矩阵的计算。

  • cv2.warpAffine(src,M,dsize,flags,mode,value)

    • M:变换矩阵
    • dsize:输出图片大小
    • flags:与resize中的插值一致
    • mode:边界外推法标志
    • value:填充边界值
  • 平移矩阵

    • 矩阵中的每个元素由(x,y)组成,(x,y)表示这个像素的坐标,假设沿x轴平移tx,沿y轴平移ty,那么最后得到的坐标为 ( x ˇ (\check{x} (xˇ, y ˘ \breve{y} y˘) = (x+tx,y+ty),用矩阵表示:

[ x ˇ y ˘ 1 ] = [ 1 0 t x 0 1 t y 0 0 1 ] [ x y 1 ] \large \begin{bmatrix} \check{x}\\ \breve{y}\\ 1\\ \end{bmatrix} =\begin{bmatrix} 1&0&t_x\\ 0&1&t_y\\ 0&0&1\\ \end{bmatrix} \begin{bmatrix} x\\ y\\ 1\\ \end{bmatrix} xˇy˘1 = 100010txty1 xy1

import cv2
import numpy as np

img1 = cv2.imread('../my_work/01.png')

# 获取原图片的尺寸与通道数
h,w,c = img1.shape
# 定义变换矩阵
M = np.float32([[1,0,100],[0,1,0]])
# OpenCV的图片尺寸是先宽后高
new = cv2.warpAffine(img1,M,(w,h))  # 平移操作

cv2.imshow("new",new)
cv2.waitKey(0)
cv2.destroyAllWindows()

1.10 仿射变换—获取旋转变换矩阵

  • OpenCv中提供了计算变换矩阵的API
  • cv2.getRotationMatrix2D(center,angle,scale)
    • center:中心点,以图片的哪个点作为旋转中心
    • angle:角度,旋转的角度,按逆时针旋转
    • scale:缩放比例
  • cv2.getAffineTransform(src[],dst[]),通过三点可以确定变换后的位置,相当于解方程,三个点对应三个方程,解出偏移参数与旋转角度
    • src:原目标三个点([ , ],[ , ],[ , ])
    • dst:变换后三个点([ , ],[ , ],[ , ])
import cv2

img1 = cv2.imread('../my_work/01.png')

# 获取原图片的尺寸与通道数
h,w,c = img1.shape
# 1.获取变换矩阵
M = cv2.getRotationMatrix2D((w/2,h/2),15,1.0)
# 2.获取变换矩阵
src = np.float32([[200,100],[50,100],[40,90]])
dst = np.float32([[200,120],[80,110],[80,50]])
M2 = cv2.getAffineTransform(src,dst)

new = cv2.warpAffine(img1,M,(w,h))  
new2 = cv2.warpAffine(img1,M2,(w,h)) 

cv2.imshow("new",new)
cv2.waitKey(0)
cv2.destroyAllWindows()

1.11 透视变换

  • 将一种坐标系变成另一种坐标系。简单来说就是把一张斜图变正

  • warpPerspecctive(img,M,dsize,....)

    • 对于透视变换来说,M是一个3*3的矩阵
  • getPerspectiveTransform(src,dst)获取透视变换矩阵,需要4个点,即图片的4个角

    • src、dst = ([ , ],[ , ],[ , ],[ , ])
import cv2
import numpy as np

img1 = cv2.imread('../my_work/01.png')

print(img1.shape)
# src是原图的4个坐标,dst是变换后的坐标
src = np.float32([[100,100],[200,100],[0,300],[250,290]])
dst = np.float32([[0,0],[210,0],[0,320],[250,290]])
# 获取变换矩阵
M = cv2.getPerspectiveTransform(src,dst)
# 透视变换
img1_new = cv2.warpPerspective(img1,M,(400,400))

cv2.imshow("new",img1_new)
cv2.waitKey(0)
cv2.destroyAllWindows()

dst = ([ , ],[ , ],[ , ],[ , ])

import cv2
import numpy as np

img1 = cv2.imread('../my_work/01.png')

print(img1.shape)
# src是原图的4个坐标,dst是变换后的坐标
src = np.float32([[100,100],[200,100],[0,300],[250,290]])
dst = np.float32([[0,0],[210,0],[0,320],[250,290]])
# 获取变换矩阵
M = cv2.getPerspectiveTransform(src,dst)
# 透视变换
img1_new = cv2.warpPerspective(img1,M,(400,400))

cv2.imshow("new",img1_new)
cv2.waitKey(0)
cv2.destroyAllWindows()
  • 25
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值