700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > (自己编写函数)Python + Opencv 图像几何变换(缩小 放大 内凹 外凸 梯形变形

(自己编写函数)Python + Opencv 图像几何变换(缩小 放大 内凹 外凸 梯形变形

时间:2020-09-19 16:55:07

相关推荐

(自己编写函数)Python + Opencv 图像几何变换(缩小 放大 内凹 外凸 梯形变形

因为之前写这个实验的时候,组织上有很多事情,所以当时,随便网上找了个 C++ 的上交了,昨天就补写了一下。这里写的缩小和方法都是等比例进行的,不是等比例的改也比较简单,这里就不改了,有兴趣的朋友可以自己尝试着改改,另外这里用的是灰度图,彩色图稍微改改就行了

比例缩小

ratio 是缩小比例,大致思路是:

1、先根据你输入的缩放比例生成一个与原图 * 缩放比例相同大小的灰度级矩阵。

2、根据书中说的首先根据缩小的倍率去算出,在原图中要隔多少个点采集一次生成新的图像,这就是我里面写的步长。比如:4*4 的 图像要缩小0.5倍,那么步长就是2 除了第一个点之外,其他每个点都要每隔两个点 取一次。

#按比例缩小def DOWNRESIZE(gray , ratio=0.8) :height , width = gray.shape[0] , gray.shape[1]resize_width , resize_height = int(width * ratio) , int(height * ratio)resize_gray = np.zeros([resize_height,resize_width],np.uint8) #创建一个和原图像 *缩小比例相同像素的空图stepsize = 1.0/ratio #原图像的采集步长for i in range (0,resize_height) :for j in range (0,resize_width) :if i == 0 and j == 0 :#缩小图(0,0)地方的像素用原图(1,1)的地方代替resize_gray[i][j] = gray[1][1]else :#缩小图其他地方的像素用此时原图对应的坐标-1的地方代替resize_gray[i][j] = gray[int(i*stepsize)-1][int(j*stepsize)-1]cv2.imshow("old",gray)cv2.imshow("Downresize",resize_gray)cv2.waitKey(0)

比例放大

比例方法,这里使用了两种方法:①最邻近插值法;②双线性插值。完全是根据概念,写的算法,概念就不重复了,可以百度,网上很多。

#按比例放大def UPSIZE(gray , ratio=1.2) :height , width = gray.shape[0] , gray.shape[1]resize_width , resize_height = int(width * ratio) , int(height * ratio)resize_gray = np.zeros([resize_height,resize_width],np.uint8)"""#最邻近插值法for i in range (0,resize_height) :for j in range (0,resize_width) :if i == 0 and j == 0 :resize_gray[i][j] = gray[int(i/ratio)+1][int(j/ratio)+1]else :resize_gray[i][j] = gray[int(i/ratio)-1][int(j/ratio)-1]"""#双线性插值for i in range (0,resize_height) :for j in range (0,resize_width) :x = i/ratioy = j/ratiop=(i+0.0)/ratio-xq=(j+0.0)/ratio-yx=int(x)-1y=int(y)-1if x+1<i and y+1<j:resize_gray[i,j]=int(gray[x,y]*(1-p)*(1-q)+gray[x,y+1]*q*(1-p)+gray[x+1,y]*(1-q)*p+gray[x+1,y+1]*p*q)cv2.imshow("old",gray)cv2.imshow("Upresize",resize_gray)cv2.waitKey(0)

水平内凹

内凹与外凸还有S型都差不多,大致思路,生成正弦波的波形,然后,从这个正弦波去确定那些地方是黑色的,最后根据每行中不是黑色的部分和原来的比重,根据之前的缩小的步长去进行每行的缩放即可。

#水平内凹def CONCAVE(gray) :RANGE = 400height, width = gray.shape[0], gray.shape[1]resize_gray = np.zeros([height, width], np.uint8)for i in range(height):# 得到正弦波的波形,即j对应的起点temp = float((width- RANGE) * math.sin(((2 * math.pi * i) / height) / 2))for j in range (int(temp+0.5),int(width-temp)) :#每行非黑色区域的长度distance = int(width-temp) - int(temp+0.5)#缩小的倍率ratio = distance / width#取点的步长stepsize = 1.0/ratio#将同意行缩小相同倍率resize_gray[i][j] = gray[i][int((j-temp)*stepsize)]cv2.imshow("old", gray)cv2.imshow("Concave", resize_gray)cv2.waitKey(0)

水平外凸

#水平外凸def CONVEX(gray) :RANGE = 400height, width = gray.shape[0], gray.shape[1]resize_gray = np.zeros([height, width], np.uint8)temp1 = []for i in range(height):# 得到正弦波的波形,即j对应的起点temp = float((width- RANGE) * math.sin(((2 * math.pi * i) / height) / 2))temp = 200 - tempfor j in range (int(temp+0.5),int(width-temp)) :#每行非黑色区域的长度distance = int(width-temp) - int(temp+0.5)#缩小的倍率ratio = distance / width#取点的步长stepsize = 1.0/ratio#将同意行缩小相同倍率resize_gray[i][j] = gray[i][int((j-temp)*stepsize)]cv2.imshow("old", gray)cv2.imshow("Convex", resize_gray)cv2.waitKey(0)

梯形形变

#梯形形变def TRAPEZOID(gray,k=0.3) :height, width = gray.shape[0], gray.shape[1]value = k*heightresize_gray = np.zeros([height, width], np.uint8)for i in range (height) :temp = int( value - k * i ) for j in range (temp,width-temp) :#每行非黑色区域的长度distance = int(width-temp) - int(temp+0.5)#缩小的倍率ratio = distance / width#取点的步长stepsize = 1.0/ratio#将同意行缩小相同倍率resize_gray[i][j] = gray[i][int((j-temp)*stepsize)]cv2.imshow("old", gray)cv2.imshow("Trapezoid", resize_gray)cv2.waitKey(0)

三角形形变

#三角形形变def TRIANGLE(gray,k=0.5) :height, width = gray.shape[0], gray.shape[1]resize_gray = np.zeros([height, width], np.uint8)for i in range (height) :temp = int( k * i ) for j in range (temp) :#每行非黑色区域的长度distance = temp#缩小的倍率ratio = distance / width#取点的步长stepsize = 1.0/ratio#将同意行缩小相同倍率resize_gray[i][j] = gray[i][int((j-temp)*stepsize)]cv2.imshow("old", gray)cv2.imshow("Triangle", resize_gray)cv2.waitKey(0)

S形形变

#S形变def SSHAPE(gray,RANGE=450) :height, width = gray.shape[0], gray.shape[1]resize_gray = np.zeros([height, width], np.uint8)for i in range(height):# 得到正弦波的波形,即j对应的起点temp = float((width - RANGE) / 2 + (width- RANGE) * math.sin((2 * math.pi * i) / height + math.pi) / 2)for j in range (int(temp+0.5),int(RANGE+temp)) :#映射关系m = int(((j-temp) * width / RANGE))if m >= width :m=width-1if m < 0 :m=0resize_gray[i,j]=gray[i,m]cv2.imshow("old", gray)cv2.imshow("Sshape", resize_gray)cv2.waitKey(0)

图片旋转

#图片旋转def ROTATE(gray, ANGLE = 45,center=None, scale=1.0) :#将角度转化为弧度""" #特别神奇的图案ANGLE = math.radians(ANGLE)height, width = gray.shape[0], gray.shape[1]resize_gray = np.zeros([800,800], np.uint8)for i in range (height) :for j in range (width) :angle = math.asin( i / width )ANGLE = angle + ANGLEx,y = int(width * math.cos(ANGLE)) , int(width * math.sin(ANGLE))resize_gray[x][y] = gray[i][j]cv2.imshow("old", gray)cv2.imshow("Rotate", resize_gray)cv2.waitKey(0)"""(height, width) = gray.shape[:2](cX, cY) = (width // 2, height // 2)M = cv2.getRotationMatrix2D((cX, cY), -ANGLE, 1.0)cos = np.abs(M[0, 0])sin = np.abs(M[0, 1])nW = int((height * sin) + (width * cos))nH = int((height * cos) + (width * sin))M[0, 2] += (nW / 2) - cXM[1, 2] += (nH / 2) - cYshuchu=cv2.warpAffine(gray, M, (nW, nH))cv2.imshow("old", gray)cv2.imshow("Rotate", shuchu)cv2.waitKey(0)

图像平移

平移很简单,就不多说了

#图片平移def HORIZONTALMOVE(gray,move_x,move_y) :height, width = gray.shape[0], gray.shape[1]resize_gray = np.zeros([height, width], np.uint8)for i in range (height) :for j in range (width) :if i + move_x < height and j + move_y < width :resize_gray[i][j] = gray[i+move_x][j+move_y]else :resize_gray [i][j] = 0cv2.imshow("old", gray)cv2.imshow("Horizeontalmove", resize_gray)cv2.waitKey(0)

主函数

def MAIN() :image = cv2.imread(r"D:\Code\Python\2.jpg")gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)while True :print("0: 按比例缩小\n1: 按比例放大\n2: 水平外凹\n3: 水平外凸\n4: 梯形变形\n5: 三角形变形\n6: S形变形\n7: 图片旋转\n8: 图片平移\n")keyinput = input ("请输入数字0—8,选择你需要的变换(按'Q'或'q'退出):\n")if keyinput == "0" :ratio = float(input("请输入缩小倍数:\n"))DOWNRESIZE(gray , ratio)continueelif keyinput == "1" :ratio = float(input("请输入放大倍数:\n"))UPSIZE(gray , ratio)continueelif keyinput == "2" :CONCAVE(gray)continueelif keyinput == "3" :CONVEX(gray)continueelif keyinput == "4" :k = float(input("请输入梯形的斜度:\n"))TRAPEZOID(gray,k)continueelif keyinput == "5" :k = float(input("请输入三角形的斜度:\n"))TRIANGLE(gray,k)continueelif keyinput == "6" :RANGE = float(input("请输入变换强度:\n"))SSHAPE(gray,RANGE)continueelif keyinput == "7" :ANGLE = float(input("请输入旋转角度:\n"))ROTATE(gray,ANGLE)continueelif keyinput == "8" :move_x = int(input("请输入x轴偏移值:\n"))move_y = int(input("请输入y轴偏移值:\n"))HORIZONTALMOVE(gray,move_x,move_y)continueelif keyinput == "Q" or "q" :breakelse :keyinput = input("您输入的字符有误,请输入 0-8 之间的数字:")

完整代码以及展示

import matplotlib.pyplot as pltfrom scipy import signalimport numpy as npimport copy as cpimport randomimport mathimport cv2import collections#按比例缩小def DOWNRESIZE(gray , ratio=0.8) :height , width = gray.shape[0] , gray.shape[1]resize_width , resize_height = int(width * ratio) , int(height * ratio)resize_gray = np.zeros([resize_height,resize_width],np.uint8) #创建一个和原图像 *缩小比例相同像素的空图stepsize = 1.0/ratio #原图像的采集步长for i in range (0,resize_height) :for j in range (0,resize_width) :if i == 0 and j == 0 :#缩小图(0,0)地方的像素用原图(1,1)的地方代替resize_gray[i][j] = gray[1][1]else :#缩小图其他地方的像素用此时原图对应的坐标-1的地方代替resize_gray[i][j] = gray[int(i*stepsize)-1][int(j*stepsize)-1]cv2.imshow("old",gray)cv2.imshow("Downresize",resize_gray)cv2.waitKey(0)#按比例放大def UPSIZE(gray , ratio=1.2) :height , width = gray.shape[0] , gray.shape[1]resize_width , resize_height = int(width * ratio) , int(height * ratio)resize_gray = np.zeros([resize_height,resize_width],np.uint8)"""#最邻近插值法for i in range (0,resize_height) :for j in range (0,resize_width) :if i == 0 and j == 0 :resize_gray[i][j] = gray[int(i/ratio)+1][int(j/ratio)+1]else :resize_gray[i][j] = gray[int(i/ratio)-1][int(j/ratio)-1]"""#双线性插值for i in range (0,resize_height) :for j in range (0,resize_width) :x = i/ratioy = j/ratiop=(i+0.0)/ratio-xq=(j+0.0)/ratio-yx=int(x)-1y=int(y)-1if x+1<i and y+1<j:resize_gray[i,j]=int(gray[x,y]*(1-p)*(1-q)+gray[x,y+1]*q*(1-p)+gray[x+1,y]*(1-q)*p+gray[x+1,y+1]*p*q)cv2.imshow("old",gray)cv2.imshow("Upresize",resize_gray)cv2.waitKey(0)#水平内凹def CONCAVE(gray) :RANGE = 400height, width = gray.shape[0], gray.shape[1]resize_gray = np.zeros([height, width], np.uint8)for i in range(height):# 得到正弦波的波形,即j对应的起点temp = float((width- RANGE) * math.sin(((2 * math.pi * i) / height) / 2))for j in range (int(temp+0.5),int(width-temp)) :#每行非黑色区域的长度distance = int(width-temp) - int(temp+0.5)#缩小的倍率ratio = distance / width#取点的步长stepsize = 1.0/ratio#将同意行缩小相同倍率resize_gray[i][j] = gray[i][int((j-temp)*stepsize)]cv2.imshow("old", gray)cv2.imshow("Concave", resize_gray)cv2.waitKey(0)#水平外凸def CONVEX(gray) :RANGE = 400height, width = gray.shape[0], gray.shape[1]resize_gray = np.zeros([height, width], np.uint8)temp1 = []for i in range(height):# 得到正弦波的波形,即j对应的起点temp = float((width- RANGE) * math.sin(((2 * math.pi * i) / height) / 2))temp = 200 - tempfor j in range (int(temp+0.5),int(width-temp)) :#每行非黑色区域的长度distance = int(width-temp) - int(temp+0.5)#缩小的倍率ratio = distance / width#取点的步长stepsize = 1.0/ratio#将同意行缩小相同倍率resize_gray[i][j] = gray[i][int((j-temp)*stepsize)]cv2.imshow("old", gray)cv2.imshow("Convex", resize_gray)cv2.waitKey(0)#梯形形变def TRAPEZOID(gray,k=0.3) :height, width = gray.shape[0], gray.shape[1]value = k*heightresize_gray = np.zeros([height, width], np.uint8)for i in range (height) :temp = int( value - k * i ) for j in range (temp,width-temp) :#每行非黑色区域的长度distance = int(width-temp) - int(temp+0.5)#缩小的倍率ratio = distance / width#取点的步长stepsize = 1.0/ratio#将同意行缩小相同倍率resize_gray[i][j] = gray[i][int((j-temp)*stepsize)]cv2.imshow("old", gray)cv2.imshow("Trapezoid", resize_gray)cv2.waitKey(0)#三角形形变def TRIANGLE(gray,k=0.5) :height, width = gray.shape[0], gray.shape[1]resize_gray = np.zeros([height, width], np.uint8)for i in range (height) :temp = int( k * i ) for j in range (temp) :#每行非黑色区域的长度distance = temp#缩小的倍率ratio = distance / width#取点的步长stepsize = 1.0/ratio#将同意行缩小相同倍率resize_gray[i][j] = gray[i][int((j-temp)*stepsize)]cv2.imshow("old", gray)cv2.imshow("Triangle", resize_gray)cv2.waitKey(0)#S形变def SSHAPE(gray,RANGE=450) :height, width = gray.shape[0], gray.shape[1]resize_gray = np.zeros([height, width], np.uint8)for i in range(height):# 得到正弦波的波形,即j对应的起点temp = float((width - RANGE) / 2 + (width- RANGE) * math.sin((2 * math.pi * i) / height + math.pi) / 2)for j in range (int(temp+0.5),int(RANGE+temp)) :#映射关系m = int(((j-temp) * width / RANGE))if m >= width :m=width-1if m < 0 :m=0resize_gray[i,j]=gray[i,m]cv2.imshow("old", gray)cv2.imshow("Sshape", resize_gray)cv2.waitKey(0)#图片旋转def ROTATE(gray, ANGLE = 45,center=None, scale=1.0) :#将角度转化为弧度""" #特别神奇的图案ANGLE = math.radians(ANGLE)height, width = gray.shape[0], gray.shape[1]resize_gray = np.zeros([800,800], np.uint8)for i in range (height) :for j in range (width) :angle = math.asin( i / width )ANGLE = angle + ANGLEx,y = int(width * math.cos(ANGLE)) , int(width * math.sin(ANGLE))resize_gray[x][y] = gray[i][j]cv2.imshow("old", gray)cv2.imshow("Rotate", resize_gray)cv2.waitKey(0)"""(height, width) = gray.shape[:2](cX, cY) = (width // 2, height // 2)M = cv2.getRotationMatrix2D((cX, cY), -ANGLE, 1.0)cos = np.abs(M[0, 0])sin = np.abs(M[0, 1])nW = int((height * sin) + (width * cos))nH = int((height * cos) + (width * sin))M[0, 2] += (nW / 2) - cXM[1, 2] += (nH / 2) - cYshuchu=cv2.warpAffine(gray, M, (nW, nH))cv2.imshow("old", gray)cv2.imshow("Rotate", shuchu)cv2.waitKey(0)#图片平移def HORIZONTALMOVE(gray,move_x,move_y) :height, width = gray.shape[0], gray.shape[1]resize_gray = np.zeros([height, width], np.uint8)for i in range (height) :for j in range (width) :if i + move_x < height and j + move_y < width :resize_gray[i][j] = gray[i+move_x][j+move_y]else :resize_gray [i][j] = 0cv2.imshow("old", gray)cv2.imshow("Horizeontalmove", resize_gray)cv2.waitKey(0)def MAIN() :image = cv2.imread(r"D:\Code\Python\2.jpg")gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)while True :print("0: 按比例缩小\n1: 按比例放大\n2: 水平外凹\n3: 水平外凸\n4: 梯形变形\n5: 三角形变形\n6: S形变形\n7: 图片旋转\n8: 图片平移\n")keyinput = input ("请输入数字0—8,选择你需要的变换(按'Q'或'q'退出):\n")if keyinput == "0" :ratio = float(input("请输入缩小倍数:\n"))DOWNRESIZE(gray , ratio)continueelif keyinput == "1" :ratio = float(input("请输入放大倍数:\n"))UPSIZE(gray , ratio)continueelif keyinput == "2" :CONCAVE(gray)continueelif keyinput == "3" :CONVEX(gray)continueelif keyinput == "4" :k = float(input("请输入梯形的斜度:\n"))TRAPEZOID(gray,k)continueelif keyinput == "5" :k = float(input("请输入三角形的斜度:\n"))TRIANGLE(gray,k)continueelif keyinput == "6" :RANGE = float(input("请输入变换强度:\n"))SSHAPE(gray,RANGE)continueelif keyinput == "7" :ANGLE = float(input("请输入旋转角度:\n"))ROTATE(gray,ANGLE)continueelif keyinput == "8" :move_x = int(input("请输入x轴偏移值:\n"))move_y = int(input("请输入y轴偏移值:\n"))HORIZONTALMOVE(gray,move_x,move_y)continueelif keyinput == "Q" or "q" :breakelse :keyinput = input("您输入的字符有误,请输入 0-8 之间的数字:")if __name__ == "__main__":MAIN()

变换结果

缩小

放大

水平内凹

水平外凸

梯形形变

三角形形变

S型形变

图片旋转

图片平移

(自己编写函数)Python + Opencv 图像几何变换(缩小 放大 内凹 外凸 梯形变形 三角型变形 S型变形 图片旋转 图片平移)

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。