版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第3章数字图像的几何运算目录图像平移Contents1图像缩放2图像旋转3图像剪切4图像镜像变换5图像透视变换6图像极坐标变换7图像平移3.1dst=cv2.warpAffine(src,M,dsize[,flags[,borderMode[,borderValue]]])其中输入输出参数如下:dst:输出图像;src:输入图像;M:2×3的变换矩阵,一般反映平移或旋转的关系;dsize:输出图像大小;flags:插值方法(int类型),默认为:cv2.INTER_LINEAR(线性插值);borderMode:边界像素模式(int类型);borderValue:边界像素填充值,默认为0(黑色)。图像平移是将图像的所有像素坐标进行水平或垂直方向移动,也就是将图像中所有像素按照指定的平移量在水平方向上沿x轴、垂直方向上沿y轴移动。图像平移是图像仿射的一种,因此它用到的函数就是仿射变换的函数,其语法格式为:插值方法以及对应说明类型说明cv2.INTER_NEAREST最近邻插值cv2.INTER_LINEAR双线性插值(默认方式)cv2.INTER_CUBIC三次样条插值cv2.INTER_AREA区域插值,根据当前像素点周边区域的像素实现当前像素点的采样cv2.INTER_LANCZOS4cv2.INTER_LINEAR_EXACT位精确双线性插值cv2.INTER_MAX差值编码掩码cv2.INTER_WARP_FILL_OUTLIERS标志,填补目标图像中的所有像素
cv2.WARP_INVERSE_MAP平移是物体位置的移动,如在(x,y)方向上的位移,移动距离设为(tx,ty),创建转换矩阵M,如下式所示:
转换矩阵M由np.float32()类型的Numpy数组产生,并将其传递给cv2.warpAffine函数。在原图像的大小不变的情况下,只是将图像平移到另一个位置,这时显示窗口尺寸变大。3.1.1显示窗口改变的图像平移【例3.1】使用仿射变换函数cv2.warpAffine()实现显示图像窗口大小改变的平移。程序代码如下:importcv2importnumpyasnpimg=cv2.imread('d:/pics/lena.jpg')#构造移动矩阵M,设在x轴方向移动50个像素和在y轴方向移动25个像素的距离M=np.float32([[1,0,50],[0,1,25]])rows,cols=img.shape[0:2]#注意rows和cols需要反置,即先列后行dst=cv2.warpAffine(img,M,(2*cols,2*rows))cv2.imshow('Origin_image',img)cv2.imshow('New_picture',dst)cv2.waitKey(0)cv2.destroyAllWindows()图中(a)为原始图像,(b)为平移后的图像。dsize这个参数是规定输出图像的尺寸,它是先列后行的。这里将输出尺寸扩大了4倍,默认的边界像素为0,所以外围都是黑色。(a)(b)在显示窗口不变的情况下,对图像进行平移,这样原图像中会有一部分不在显示窗口中,将会有部分图像丢失。3.1.2显示窗口不变的图像平移【例3.2】使用仿射变换函数cv2.warpAffine()实现图像显示窗口大小不改变的平移。程序代码如下:importcv2importnumpyasnpimg=cv2.imread('d:/pics/lena.jpg')#构造移动矩阵M,设定在x轴方向移动的距离和在y轴方向移动的距离M=np.float32([[1,0,50],[0,1,25]])rows,cols=img.shape[0:2]#注意这里rows和cols需要反置,即先列后行dst=cv2.warpAffine(img,M,(cols,rows))cv2.imshow('Origin_image',img)cv2.imshow('New_image',dst)cv2.waitKey(0)cv2.destroyAllWindows()图中(a)为原始图像,(b)为平移后的图像。可以看到,只要将例3.1代码改为:dst=cv2.warpAffine(img,M,(cols,rows)),结果将会实现显示图像窗口不变的平移。(a)(b)在仿射变换的实际应用中,原始图像中的所有平行线在输出图像中希望继续保持平行,我们就需要输入图像中的三个点及其在输出图像中的对应位置,然后通过cv2.getAffineTransform()函数将创建一个2×3变换矩阵,并将该矩阵传递给cv2.warpAffine()函数,实现图像中的平行线在仿射变换前后一直保持平行。
函数cv2.getAffineTransform()语法格式为:3.1.3仿射变换应用实例M=cv2.getAffineTransform(src,dst)其中输入输出参数为:src:原始图像中的三个点的坐标;dst:变换后的这三个点对应的坐标;M:根据三个对应点求出的仿射变换矩阵。3.1.3仿射变换应用实例importcv2importnumpyasnpfrommatplotlibimportpyplotaspltimg=cv2.imread('d:/pics/drawpic.png')rows,cols,ch=img.shape#选择合适的数据点pts1=np.float32([[50,50],[200,50],[50,200]])pts2=np.float32([[10,100],[200,50],[100,250]])#创建M变换矩阵M=cv2.getAffineTransform(pts1,pts2)#仿射变换dst=cv2.warpAffine(img,M,(cols,rows))#输出显示plt.subplot(121),plt.imshow(img),plt.title('Input')plt.subplot(122),plt.imshow(dst),plt.title('Output')plt.show()(a)(b)【例3.3】在图像选择合适的点(蓝色点),创建变换矩阵,实现仿射变换。程序代码如下:程序运行结果如图所示。图像缩放3.2dst=cv2.resize(src,dsize[,fx[,fy[,interpolation]]])其中输入参数:src:输入图像;dsize:输出图像的尺寸,与下面的比例因子二选一;fx:沿水平轴的比例因子;fy:沿垂直轴的比例因子;interpolation:插值方法,默认为cv2.INTER_NEAREST(最近邻插值)。图像缩放有两种方法:一种是通过设置缩放比例,来对图像进行放大和缩小;另一种是直接设置图像的大小,不需要缩放因子。图像缩放,就是对图像进行放大或缩小的改变,其本质就是改变图像的宽度和高度,可以放大宽高,也可以缩小宽高。
图像缩放算法主要有最近邻域插值算法、双线性插值算法、立方插值算法和像素关系重采样算法。其中,OpenCV默认使用双线性插值算法对图像进行缩放。
在OpenCV中可以调用resize函数对图像进行缩放。【例3.4】分别通过设置缩放比例的方法和直接设置图像的大小方法,利用仿射变换函数cv2.warpAffine()实现对图像的缩放。程序代码如下:importcv2img=cv2.imread('d:/pics/lena.jpg')#方法一:通过设置缩放比例,来对图像进行放大或缩小dst1=cv2.resize(img,None,fx=1.2,fy=1.2,interpolation=cv2.INTER_CUBIC)#方法二:直接设置图像的大小,不需要缩放因子height,width=160,160dst2=cv2.resize(img,(height,width),interpolation=cv2.INTER_LANCZOS4)cv2.imshow('Original_image',img)cv2.imshow('Result1',dst1)cv2.imshow('Result2',dst2)cv2.waitKey(0)cv2.destroyAllWindows()图中,(a)为原始图像,(b)是通过设置放缩比例放大的图像,放缩比例为1.2,(c)为通过直接设置图像大小,对原始图像缩小后的图像。(a)(b)(c)图像旋转3.3M=cv2.getRotationMatrix2D(center,angle,scale)其中输入参数:center:图片的旋转中心;angle:旋转角度;scale:缩放比例,0.5表示缩小为原来的一半,这个参数还能表示旋转方向,正数表示逆时针,负数表示顺时针旋转。通过这个函数可以直接根据给定中心、角度和缩放比例的值自动求出变换矩阵,然后将这个矩阵作为仿射变换函数的M参数,代入cv2.warpAffine函数中即可实现旋转操作。
图像旋转是指图像在某个位置转动一定角度,旋转中图像仍保持原始尺寸。图像旋转后图像的水平对称轴、垂直对称轴及中心坐标原点都可能会发生变化,因此需要对图像旋转中的坐标进行相应转换。旋转后图像的大小一般会改变,即可以把转出显示区域的图像截去,或者扩大图像窗口显示范围来显示全部图像。
旋转也是仿射变换的一种,所以操作的函数还是cv2.warpAffine,但是它的变换矩阵一般不像平移那样简单,所以OpenCV提供了一个专门用于图像旋转变换矩阵的函数cv2.getRotationMatrix2D(),其语法格式为:【例3.5】使用cv2.getRotationMatrix2D函数实现图像的顺时针、逆时针旋转。程序代码如下:importcv2img=cv2.imread('d:\pics\lena.jpg')rows,cols=img.shape[:2]#旋转45度M=cv2.getRotationMatrix2D((cols/2,rows/2),45,1)dst=cv2.warpAffine(img,M,(cols,rows),borderValue=(255,255,255))cv2.imshow('Image',img)cv2.imshow('Rotationimage',dst)cv2.waitKey(0)cv2.destroyAllWindows()图(a)为原始图像,图(b)为逆时针旋转后的图像。若将scale改为-1,即可进行顺时针旋转:M=cv2.getRotationMatrix2D((cols/2,rows/2),45,-1),顺时针旋转后程序运行结果如下图所示。
(a)(b)图(a)为原始图像,图(b)为顺时针旋转后的图像。【例3.6】通过上述M变换矩阵实现图像边缘无剪切的旋转。程序代码如下:importcv2importnumpyasnpimg=cv2.imread("d:/pics/lena.jpg",cv2.IMREAD_COLOR)h,w,c=img.shapeM=np.zeros((2,3),dtype=np.float32)alpha=np.cos(np.pi/4.0)beta=np.sin(np.pi/4.0)#初始旋转矩阵M[0,0]=alphaM[1,1]=alphaM[0,1]=betaM[1,0]=-betacx=w/2cy=h/2tx=(1-alpha)*cx-beta*cyty=beta*cx+(1-alpha)*cyM[0,2]=txM[1,2]=ty#更改为全尺寸bound_w=int(h*np.abs(beta)+w*np.abs(alpha))bound_h=int(h*np.abs(alpha)+w*np.abs(beta))#添加中心位置迁移M[0,2]+=bound_w/2-cxM[1,2]+=bound_h/2-cydst=cv2.warpAffine(img,M,(bound_w,bound_h))cv2.imshow('Originimage',img)cv2.imshow("rotatewithoutcropping",dst)cv2.waitKey(0)cv2.destroyAllWindows()(a)(b)图为图像边缘无剪切的旋转的结果,图(a)为原始图像,图(b)为旋转后的图像。图像剪切3.4图像剪切是指将图像中我们感兴趣的区域(ROI)以外的区域去除,可以将图像剪切分为规则剪切和不规则剪切两种类型。规则剪切:指剪切图像的边界范围是一个矩形,剪切时只需要通过左上角和右下角两点的坐标,就可以确定图像的裁剪位置。不规则剪切:指剪切图像的边界范围是任意多边形,剪切时必须首先生成一个完整的闭合多边形区域。【例3.7】规则剪切:对图像进行规则裁剪。程序代码如下:importcv2img=cv2.imread('d:/pics/lena.jpg')img1=img[30:160,20:180]#剪切区域cv2.imshow("Original",img)cv2.imshow("Result",img1)cv2.waitKey(0)cv2.destroyAllWindows()(a)(b)图(a)为原始图像,图(b)为逆时针旋转后的图像。【例3.8】不规则剪切:首先通过鼠标左键在图像上选取多个任意点,连接成不规则的形状;然后双击鼠标左键,剪切出图像的掩模区域和图像区域;最后点击鼠标右键将图像上的连线清除掉。程序代码如下:importcv2importnumpyasnpdefOn_Mouse(event,x,y,flags,param):globalimg,point1,point2,count,pointsMaxgloballsPointsChoose,tpPointsChoose#存入选择的点
globalpointsCount#对鼠标按下的点计数
globalimg2,ROI_bymouse_flagimg2=img.copy()#保证每次都重新在原图画
ifevent==cv2.EVENT_LBUTTONDOWN:#左键点击
pointsCount=pointsCount+1print('pointsCount:',pointsCount)point1=(x,y)print(x,y)cv2.circle(img2,point1,5,(0,255,0),2)#画出点击的点
#将选取的点保存到list列表里
lsPointsChoose.append([x,y])#用于转化为darry提取多边形ROItpPointsChoose.append((x,y))#用于画点
#将鼠标选的点用直线连起来
print(len(tpPointsChoose))foriinrange(len(tpPointsChoose)-1):print('i',i)cv2.line(img2,tpPointsChoose[i],tpPointsChoose[i+1],(0,0,255),2)cv2.imshow(‘src’,img2)#----右键点击,清除轨迹-------------ifevent==cv2.EVENT_RBUTTONDOWN:print("right-mouse")pointsCount=0tpPointsChoose=[]lsPointsChoose=[]print(len(tpPointsChoose))foriinrange(len(tpPointsChoose)-1):print('i',i)cv2.line(img2,tpPointsChoose[i],tpPointsChoose[i+1],(0,0,255),2)cv2.imshow('src',img2)
#----双击鼠标,结束选取,绘制感兴趣区域------ifevent==cv2.EVENT_LBUTTONDBLCLK:ROI_byMouse()ROI_bymouse_flag=1lsPointsChoose=[]
defROI_byMouse():globalsrc,ROI,ROI_flag,mask2mask=np.zeros(img.shape,np.uint8)pts=np.array([lsPointsChoose],32)#pts是多边形的顶点列表
pts=pts.reshape((-1,1,2))#OpenCV中需要先将多边形的顶点坐标变成顶点数×1×2维的矩阵,再来绘制
mask=cv2.polylines(mask,[pts],True,(255,255,255))#画多边形
mask2=cv2.fillPoly(mask,[pts],(255,255,255))#填充多边形
cv2.imshow('mask',mask2)
#掩模图像与原图像进行“位与”操作
ROI=cv2.bitwise_and(mask2,img)cv2.imshow('ROI',ROI)if__name__=='__main__':#选择点设置
lsPointsChoose=[]tpPointsChoose=[]pointsCount=0count=0pointsMax=6img=cv2.imread('d:/pics/lena.jpg')ROI=img.copy()dWindow('src')cv2.setMouseCallback('src',On_Mouse)cv2.imshow('src',img)cv2.waitKey(0)
cv2.destroyAllWindows()(a)鼠标选取过程
(b)选取后的范围
(c)原图剪切后的图像图像镜像变换3.5dst=cv2.flip(src,flipCode)其中输入参数:src:输入图像;flipCode:翻转方向。用于指定镜像翻转的类型,其中0表示绕x轴翻转,即垂直镜像翻转;1表示绕y轴翻转,即水平镜像翻转;-1表示绕x轴、y轴两个轴翻转,即对角镜像翻转。图像的镜像变换分为三种:水平镜像、垂直镜像和对角镜像。水平镜像以图像垂直中线为轴,将图像的像素左右进行对换,也就是将图像的左半部和右半部对调。垂直镜像则是以图像的水平中线为轴,将图像的上半部分和下半部分对调。对角镜像翻转是以图像水平中轴线和垂直中轴线的交点为中心进行镜像对换,也就是以图像对角线为中心进行的镜像变换。OpenCV提供了对图像进行镜像变换的函数flip,其格式为:【例3.9】使用cv2.flip函数实现图像的水平、垂直以及对角镜像变换。程序代码如下:importcv2frommatplotlibimportpyplotaspltimg=cv2.imread('d:/pics/lena.jpg')img=cv2.cvtColor(img,cv2.COLOR_BGR2RGB)img0=cv2.flip(img,1)img1=cv2.flip(img,0)img2=cv2.flip(img,-1)plt.subplot(221),plt.imshow(img)plt.axis('off'),plt.title('Original')plt.subplot(222),plt.imshow(img0)plt.axis('off'),plt.title('Horizontal')plt.subplot(223),plt.imshow(img1)plt.axis('off'),plt.title('Vertical')plt.subplot(224),plt.imshow(img2)plt.axis('off'),plt.title('Diagonal')plt.show()图中图像的镜像变换(其中左上为原始图像,右上为水平镜像变换后的图像,左下为垂直镜像变换后的图像,右下对角镜像变换后的图像)图像透视变换3.6M=cv2.getPerspectiveTransform(src,dst[,solveMethod])其中输入参数为:src:表示透视变换前的4个点的位置;dst:表示透视变换后的4个对应点的位置。透视变换是将图片投影到一个新的视平面,也称作投影映射。在透视变换中,原始图像中的所有平行线在输出图像中希望继续保持平行,我们就需要输入图像中的4个点及其在输出图像中的对应位置,在这4个点中,其中3个不能共线。然后通过OpenCV提供的求透视变换矩阵cv2.getPerspectiveTransform()函数创建一个3×3变换矩阵,并将该矩阵传递给透视变换函数cv2.warpPerspective(),实现图像中的平行线在透视变换前后始终保持平行。透视变换矩阵的函数cv2.warpPerspective语法格式如下:透视变换函数cv2.warpPerspectiv格式如下:dst=cv2.warpPerspective(src,M,dsize[,flags[,borderMode[,borderValue]]])其中输入参数为:src:原始图像。M:透视变换矩阵。dsize:输出图像的尺寸。【例3.10】在图像上选择合适的点,创建透视变换矩阵,实现透视变换。程序代码如下:importcv2importnumpyasnpfrommatplotlibimportpyplotaspltimg=cv2.imread('d:/pics/weiqi1.jpg')img=cv2.cvtColor(img,cv2.COLOR_BGR2RGB)rows,cols,ch=img.shape#选择合适数据点pts1=np.float32([[50,60],[560,50],[30,580],[590,590]])pts2=np.float32([[0,0],[600,0],[0,600],[600,600]])#创建M透视变换矩阵M=cv2.getPerspectiveTransform(pts1,pts2)#透视变换dst=cv2.warpPerspective(img,M,(640,400))#显示输入输出图像plt.subplot(121),plt.imshow(img),plt.title('Input')plt.subplot(122),plt.imshow(dst),plt.title('Output')plt.show()(a)原始图像
(b)透视变换后图像图像极坐标变换3.7极坐标变换就是将图像在直角坐标系与极坐标系中互相转换,极坐标的转换常用于对圆形如钟表、圆盘等图像进行转换,圆形图案边缘上的文字经过极坐标变换后可以垂直的排列在新图像的边缘,便于对文字的识别和检测。OpenCV提供了cv2.cartToPolar()函数实现由直角坐标系(或称笛卡尔坐标)转换为极坐标系,cv2.polarToCart()函数由极坐标系转换为直角坐标系。3.7.1数据点坐标系间的转换【例3.11】将数据点由直角坐标系(x,y)转换为极坐标系(r,theta),再由极坐标系转换为直角坐标系。程序代码如下:importmathimportcv2importnumpyasnpx,y=3,5print('直角坐标x=',x,'\n直角坐标y=',y)#math库函数计算center=[0,0]#中心点r=math.sqrt(math.pow(x-center[0],2)+math.pow(y-center[1],2))theta=math.atan2(y-center[1],x-center[0])/math.pi*180#转换为角度print('math库r=',r)print('math库theta=',theta)#opencv也提供了极坐标变换的函数x1=np.array(x,np.float32)y1=np.array(y,np.float32)#变换中心为原点,若想为(2,3)需x1-2,y1-3r1,theta1=cv2.cartToPolar(x1,y1,angleInDegrees=True)#当angleInDegrees是True时,返回值为angle角度,否则为弧度print('OpenCV库函数r=',r1)print('OpenCV库函数thetar=',theta1)#反变换,即将极坐标变为笛卡尔坐标。(r,theta)变换为(x,y)x1,y1=cv2.polarToCart(r1,theta1,angleInDegrees=True)print('极坐标变为笛卡尔坐标x=',np.round(x1[0]))print('极坐标变为笛卡尔坐标y=',np.round(y1[0]))程序运行结果输出如下:直角坐标x=3直角坐标y=5math库函数r=5.830951894845301math库函数theta=59.03624346792648OpenCV库函数r=[[5.8309517]]OpenCV库函数thetar=[[59.039936]]极坐标变为直角坐标x=[3.]极坐标变为直角坐标y=[5.]dst=cv2.LogPolar(src,center,M,intflags=CV2_INTER_LINEAR+CV2_WARP_FILL_OUTLIERS)其中输入输出参数为:dst:直角坐标变换后输出图像,与原图像具有相同的数据类型和通道数;src:原图像,可以是灰度图像或者彩色图像;center:直角坐标变换时直角坐标的原点坐标;M:幅度比例参数;flags:插值方法。CV_WARP_FILL_OUTLIERS表示填充所有目标图像像素。OpenCV直角坐标系转换为极坐标系有2个函数:其一是cv2.logPolar函数是把数据从直角坐标系转到对数极坐标系,其二是cv2.linearPolar函数把数据从直角坐标系转到线性极坐标系。其中cv2.logPolar直角坐标系转换为极坐标系函数语法格式为:3.7.2图像数据坐标系间的转换【例3.12】图像数据由直角坐标向极坐标的转换。程序代码如下:importcv2importmathimg=cv2.imread('d:/pics/clock.jpg')h,w=img.shape[0:2]maxRadius=math.hypot(w/2,h/2)m=w/math.log(maxRadius)log_polar=cv2.logPolar(img,(w/2,h/2),m,cv2.WARP_FILL_OUTLIERS+cv2.INTER_LINEAR)linear_polar=cv2.linearPolar(img,(w/2,h/2),m,cv2.WARP_FILL_OUTLIERS+cv2.INTER_LINEAR)dst=cv2.transpose(log_polar)#图像转置dst=cv2.flip(dst,0)#图像垂直镜像lin_dst=cv2.transpose(linear_polar)#图像转置lin_dst=cv2.flip(lin_dst,0)#图像垂直镜像cv2.imshow("Original",img)cv2.imshow("Log_polar",log_dst)cv2.imshow("Linear_polar",lin_dst)cv2.waitKey(0)cv2.destroyAllWindows()图(a)为直角坐标系的钟表,图(b)为对数极坐标系钟表,图(c)为线性极坐标系的钟表。(a)
(b)
(c)dst=cv2.warpPolar(src,dsize,center,maxRadius,flags)其中输出、输入参数为:dst:极坐标变换后输出图像,与原图像具有相同的数据类型和通道数;src:原图像,可以是灰度图像或者彩色图像;dsize:输出图像的尺寸;center:极坐标变换时极坐标的原点坐标;maxRadius:变换时边界圆的半径,它也决定了逆变换时的比例参数;flags:插值方法与极坐标映射方法标志,如表所示。在OpenCV库中提供了实现图像极坐标变换的函数cv2.warpPolar,它的语法格式是:3
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 医院公益岗工作制度
- 医院草药房工作制度
- 十个专项组工作制度
- 单位消防员工作制度
- 卫健委安全工作制度
- 卫生院护理工作制度
- 厨房初加工工作制度
- 县委办保密工作制度
- 黑河市2026国家开放大学计算机科学与技术-期末考试提分复习题(含答案)
- 县网络安全工作制度
- 小儿猩红热的护理
- 中国船舶集团校招面笔试题及答案
- 2025-2030中国珠宝首饰设计制造市场艺术风格分析及品牌营销策略规划
- 2026江苏苏州市健康养老产业发展集团有限公司下属子公司招聘44人(第一批)笔试历年典型考点题库附带答案详解
- 2026年临沂市工业学校公开招聘教师(32名)笔试参考题库及答案解析
- 建筑行业绩效考核管理办法
- 初中地理新课标测试题及答案
- 浙江强基联盟2026年3月高三语文联考作文题目解析及范文:有的时候人们主动选择预制
- 2026年大学生军事理论知识竞赛题库及答案(共80题)
- T-ZAHA 011-2025 智慧牧场建设指南
- 2026年贵州贵阳云岩区街道招聘笔试模拟试题附答案
评论
0/150
提交评论