OpenCV图象变更二 投影变更与极坐标变更完成圆形图象修改
Keras入门(六)模型训练实时可视化
投影变更
在放射变更中,物体是在二维空间中变更的。假如物体在三维空间中发生了扭转,那末这类变更就成为投影变更,在投影变更中就会涌现暗影或许遮挡,我们能够应用二维投影对三维投影变更举行模块化,来处置惩罚暗影或许遮挡。在OpenCV中有相似于getAffineTransform函数:getPerspectiveTransform(src,dst)函数 用来处置惩罚盘算投影变更矩阵。与getAffineTransform函数差别的是传入的参数是三维空间坐标系的空间坐标,也就是4*2的二维ndarray,个中每一行代表一个坐标而且传入的数据范例必需为float32.示例:
import cv2
import numpy as np
src=np.array([[0,0],[100,0],[0,100],[100,100]],np.float32)
dst=np.array([[100,10],[100,10],[50,70],[200,150]],np.float32)
P=cv2.getPerspectiveTransform(src,dst)
print(P)
运转效果:
[[-7.77156117e-16 -1.00000000e+00 1.00000000e+02]
[-2.77555756e-15 -1.00000000e-01 1.00000000e+01]
[-2.66713734e-17 -1.00000000e-02 1.00000000e+00]]
由效果能够看出当前输出的范例是float64.关于仿射变更在OpenCV中供应了以下的函数
cv2.warpPerspective(src,M,dsize[,dst[,flags[,borderMode[,borderValue]]]])
输入的矩阵范例是3行3列的投影变更矩阵。示例:
import cv2
import numpy as np
import matplotlib
def Perspect(path):
img=cv2.imread(path,cv2.IMREAD_GRAYSCALE)
if not isinstance(img, np.ndarray):
print('PASS')
pass
else:
h,w=img.shape
#设置变更坐标变化
src=np.array([[0,0],[w-1,0],[0,h-1],[w-1,h-1]],np.float32)
dst=np.array([[100,100],[w/3,100],[100,h-1],[w-1,h-1]],np.float32)
#盘算投影变更矩阵
P=cv2.getPerspectiveTransform(src,dst)
#应用变化矩阵举行投影变更
r=cv2.warpPerspective(img,P,(w,h),borderValue=126)
#显现图象
cv2.imshow('A',img )
cv2.imshow('B',r)
cv2.waitKey(0)
cv2.destroyAllWindows()
print(P)
Perspect('img/aa.jpg')
极坐标变更
极坐标变更重要处置惩罚校订图象中的圆形物体或许在圆形中物体
1.将笛卡尔坐标转换为极坐标
(r=sqrt{(x-(overline{x})^2)+(y-(overline{y})^2)})
[theta= left{ begin{matrix} 2pi +arctan2(y-overline{y},x-overline{x}), &y-overline{y}leq0 arctan2(y-overline{y},x-overline{x},&y-overline{y}>0 end{matrix} right} ]
以变更中间为圆心的统一个圆心上的点,在极坐标系(theta)or中显现为一条直线。个中(theta)的取值局限为[0,2(pi)],函数arctan2返回的角度和笛卡尔积坐标点地点的象限有关联。举例,(9,15)以(2,10)为中间举行极坐标的变更,示例代码:
#半径转换 r=math.sqrt(math.pow(9-2,2)+math.pow(15-10,2)); #角度转换 theta=math.atan2(15-10,9-2)/math.pi*180
该示例能够如许明白,先把坐标原点移动到(2,10)处,则(9,15)平移后的坐标变成(7,5),然后再以(0,0)为中间举行转换。在OpenCV中的函数cartToPolar(x,y[,magnitude[, angle[,angleIndegress ]]])完成的就是将原点移动到变更中间后的笛卡尔积坐标向极坐标的变更,返回值magnitude,angle是与参数x,y具有雷同尺寸和数据范例的ndarray。angleInDegrees的值为True时,返回值为角度,反之返回值为弧度。
比方:盘算(0,0)、(1,0)、(2,0)、(0,1)、(1,1)、(2,1)、(0,2)、(1,2)、(2,2)这九个点以(1,1)为中间举行的坐标转换。首先将坐标原点移动到(1,1)处,依据平移放射矩阵盘算出这九个点平移后的新坐标值,然后应用函数cartToPolar举行极坐标的转换。代码示意为:
import cv2
import numpy as np
x=np.array([[0,1,2],[0,1,2],[0,1,2]],np.float64)-1
y=np.array([[0,0,0],[1,1,1],[2,2,2]],np.float64)-1
r,theta = cv2.cartToPolar(x,y,angleInDegrees=True)
print("r: %s"%r)
print("theta: %s"%theta)
运转效果:
能够看到实行后的极坐标((theta),r)
以上九个点的图象示意就是以(1,1)为圆心的九个点,间隔变更中间相称的点转换为极坐标后在极坐标系中位于统一条直线上。如许就直观的给出了极坐标变更是怎样校订图象中的圆形物体或许圆环中的物体的。
2.将极坐标转换为笛卡儿坐标
极坐标的变更是可逆的,在已知极坐标和笛卡儿坐标的条件下,盘算哪一个笛卡儿坐标以((overline{x}),(overline{y}))为中间的极坐标变更时((theta),r),盘算公式为:
[ x= overline{x}+rcostheta, y=overline{y}+rsintheta]
在OpenCV中的完成函数是 cv2.polarToCart(magnitude,angle[,x[, y[, angleInDegrees ]]] )来完成将极坐标转化为笛卡尔坐标。其参数与cartToPolar参数相似。代码举例 完成 依据极坐标系的(30,20),(31,21),(30,10),(30,10)四个点盘算迪卡儿坐标系的哪四个点以(-6,6)为中间变更获得的。
import cv2
import numpy as np
# 将迪卡儿坐标转换为极坐标
angle = np.array([[30, 31], [30, 30]], np.float32)
r = np.array([[20, 21], [10, 10]], np.float32)
x, y = cv2.polarToCart(r, angle, angleInDegrees=True)
print("变更中间为(0,0) 获得的四个迪卡儿坐标")
print("x: %s" % x)
print("y: %s" % y)
x+=-6
y+=6
print("变更中间为(-6,6) 获得的四个迪卡儿坐标")
print("x: %s" % x)
print("y: %s" % y)
运转效果:
3.应用极坐标变更完成图象修改
我们应用极坐标和迪卡儿坐标的意义对应关联获得O的每个像素值:
[O(r,theta)=f_{1}( overline{x}+rcostheta,overline{y}+rsintheta)]
此公式中的图象输出是以1为步长举行离散化的,然则如许的化输出的图象矩阵会涌现失真的状况,丧失跟多的图象信息,。我们的解决方法是将与((overline{x}),(overline{y}))的间隔局限为[(r_{min}),(r_{max})]而且角度局限在 ([theta_{min},theta_{max}])内的点举行极坐标向笛卡尔坐标的变更,而且举行离散化。(theta)的变更步长(theta_{step})平常取(tfrac{360}{180*N}),N(ge) 2,此时输出的宽为w (approx) (tfrac{r_{max}-r_{min}}{r_{step}}) 图象矩阵的第i行第j列可经由过程以下的公式举行盘算:
[O(i,j)= F_1 (overline{x}+(r_{min}+r_{step}i)* cos(theta_{min}+theta_{step}j),overline{y}+(r_{min}+r_{step}i)*sin(theta_{min}+theta_{step}j)) ]
下面我们经由过程一个详细的实例来完成极坐标的变更:将一个圆环图象变成矩形图象
import cv2
import numpy as np
import sys
#完成图象的极坐标的转换 center代表及坐标变更中间‘;r是一个二元元组,代表最大与最小的间隔;theta代表角度局限
#rstep代表步长; thetastap代表角度的变化步长
def polar(image,center,r,theta=(0,360),rstep=0.5,thetastep=360.0/(180*4)):
#获得间隔的最小值、最大值
minr,maxr=r
#角度的最小局限
mintheta,maxtheta=theta
#输出图象的高、宽 O:指定外形范例的数组float64
H=int((maxr-minr)/rstep)+1
W=int((maxtheta-mintheta)/thetastep)+1
O=125*np.ones((H,W),image.dtype)
#极坐标转换 应用tile函数完成W*1铺成的r个矩阵 并对生成的矩阵举行转置
r=np.linspace(minr,maxr,H)
r=np.tile(r,(W,1))
r=np.transpose(r)
theta=np.linspace(mintheta,maxtheta,W)
theta=np.tile(theta,(H,1))
x,y=cv2.polarToCart(r,theta,angleInDegrees=True)
#近来插值法
for i in range(H):
for j in range(W):
px=int(round(x[i][j])+cx)
py=int(round(y[i][j])+cy)
if((px>=0 and px<=w-1) and (py>=0 and py<=h-1)):
O[i][j]=image[py][px]
return O
if __name__=="__main__":
img = cv2.imread("img/yu.jpg", cv2.IMREAD_GRAYSCALE)
# 传入的图象宽:600 高:400
h, w = img.shape[:2]
print("h:%s w:%s"%(h,w))
# 极坐标的变更中间(300,200)
cx, cy = 300, 200
# 圆的半径为10 色彩:灰 最小位数3
cv2.circle(img, (int(cx), int(cy)), 10, (255, 0, 0, 0), 3)
L = polar(img, (cx, cy), (100, 350))
# 扭转
L = cv2.flip(L, 0)
# 显现与输出
cv2.imshow('img', img)
cv2.imshow('O', L)
cv2.waitKey(0)
cv2.destroyAllWindows()
赛狗日源码分享 《Head First C#》第三版