本文介绍了覆盆子pi:校准相机和图像的不失真的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述 29岁程序员,3月因学历无情被辞! 我想从图像中删除鱼眼效果,所以我需要相机矩阵和失真高效。这就是为什么我创建了 cal.py 文件。 当我运行那个文件它给我相机矩阵和失真效率我必须在 undist.py 文件中解除图像。现在每次我得到相同的RMS,相机矩阵,失真系数如附图所示(输出)。 把这个参数放在undist.py文件中,这是给我空白图像..如何解决这个问题?PLz帮助我...感谢在advance.i有捕获8图像和一个棋盘模式的示例图像如下图所示。 这是我的cal.py和undist.py文件: cal.py #!/ usr / bin / env python import numpy as np import cv2 import cv import os 从公共导入splitfn USAGE ='''USAGE:calib.py [ - -save< filename>] [--debug< output path>] [--square_size] [< image mask>]''' if __name__ =='__main__': import sys ,getopt from glob import glob camera_matrix = cv.CreateMat(3,3,cv.CV_32FC1) dist_coefs = cv.CreateMat(4,1,cv.CV_32FC1) args,img_mask = getopt.getopt(sys.argv [1:],'',['save =','debug =','square_size =']) args = dict(args) img_mask ='image * .jpg' img_names = glob(img_mask) debug_dir = args.get(' - debug') square_size = float(args.get(' - square_size ',1.0)) pattern_size =(9,6) pattern_points = np.zeros((np.prod(pattern_size),3),np.float32) pattern_points [:, 2] = np.indices(pattern_size).T.reshape(-1,2) pattern_points * = square_size obj_points = [] img_points = [] h,w = 0,0 for img_names中的fn: print'processing%s ...'%fn, img = cv2.imread(fn,0)h,w = img .shape [:2] found,corners = cv2.findChessboardCorners(img,pattern_size)如果找到: term =(cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_COUNT,30,0.1) cv2.cornerSubPix(img,corner,(5,5),(-1,-1),term)如果debug_dir: vis = cv2.cvtColor(img,cv2.COLOR_GRAY2BGR) cv2.drawChessboardCorners(vis,pattern_size,corner,found) path,name,ext = splitfn(fn) cv2.imwrite('%s /%s_chess.png'%(debug_dir, name),vis)如果没有找到: print'chessboard not found' continue img_points.append(corners.reshape(-1,2)) obj_points.append(pattern_points) print'ok' rms,camera_matrix,dist_coefs,rvecs,tvecs = cv2.calibrateCamera(obj_points,img_points,(w,h)) print ,rms printcamera matrix:\\\,camera_matrix printdistortion coefficients:,dist_coefs.ravel() cv2.destroyAllWindows() undist.py #!/ usr / bin / env python import smtplib 导入时间 import subprocess 来自email.MIMEMultipart import MIMEMultipart 从email.MIMEBase导入MIMEBase 从email.MIMEText导入MIMEText 从email.MIMEImage导入MIMEImage 导入RPi.GPIO为GPIO 导入映像导入cv2 import numpy as np #定义这些一次;使用它们两次! strFrom ='[email protected]' strTo ='[email protected]' #create email #创建根消息并填写from,to和subj $ msgRoot = MIMEMultipart() msgRoot ['Subject'] ='fisheye到正常图像' msgRoot ['From'] = strFrom msgRoot ['To'] = strTo GPIO.setmode(GPIO.BCM) GPIO.setup(4,GPIO.IN) print 按钮发送电子邮件 GPIO.setup(4,GPIO.IN,pull_up_down = GPIO.PUD_UP) while True: input = GPIO.input(4) if input == False: printbutton pressed subprocess.Popen([fswebcam, - r 640x480,image4.jpg]) time.sleep )#将参数复制到数组 K = np.array([[271.40850489,0,306.38705314],[0,271.08688021,234.03565551],[0,0,1]])d = np.array ([-3.55461489e-01,1.45402260e-01,-1.33385142e-03,1.63603888e-04,-2.96650946e-02])#只使用前两个术语(无翻译) #读取您的一个图片 img = cv2.imread(image4.jpg)h,w = img.shape [:2] #undistort newcamera ,roi = cv2.getOptimalNewCameraMatrix(K,d,(w,h),0) newimg = cv2.undistort(img,K,d,None,newcamera) cv2.imwrite (original.jpg,img) cv2.imwrite(undistorted.jpg,newimg) #此示例假定映像位于当前目录 #fp = open('image4.jpg','rb') #msgImage = MIMEImage(fp.read())#fp.close()#msgRoot.attach (msgImage)#send mail #s = smtplib.SMTP('smtp.gmail.com',587)#s.starttls()#s.login '[email protected]','password')#s.sendmail(strFrom,strTo,plt.show())#s.close() print发送 time.sleep(0.2) 这是我的输入图片: 这是我的输出图片: 解决方案我会做一个答案来总结评论中解决的所有问题(这种方式,未来的读者不必阅读所有的) 按照教学课程此处,以更好地了解您应该做什么以及使用哪些功能。 检查您的相机矩阵是否具有正确的形式: [f_x s c_x 0 f_y c_y 0 0 1] 确保每一步都要正确加载图片,并确保图片正确无误(使用 pre> newcamera,roi = cv2.getOptimalNewCameraMatrix(K,d,(w,h),0) newimg = cv2.undistort(img,K,d,None,newcamera ) 为什么,从opencv 文档,我们有: cv2.getOptimalNewCameraMatrix(cameraMatrix,distCoeffs,imageSize,alpha [,newImgSize [,centerPrincipalPoint]])→retval,validPixROI 和这意味着新的相机矩阵也给你一个新的有效的大小!更具体地说:但是undistort函数会自动执行 initUndistortRectifyMap ...并且没有办法传递 newImageSize 。因此,基本上你有两个选项。 使用 newcamera 矩阵,执行 undistort ,则应手动执行所有操作....这意味着您必须执行 initUndistortRectifyMap 和 remap 使用 calibrateCamera 功能。这种方式不会有此缩放效果,但您可能会有一些额外的黑色像素代表因修正而无法看到的区域。 如果没有,它将总是给你这种缩放效果,因为它不会显示未失真区域的无效像素(黑色像素)。 I want to remove fisheye effect from image, so I need camera matrix and distortion cofficient. That's why I created cal.py file.When I run that file it give me camera matrix and distortion efficient which I have to put in undist.py file to undistort the image. now every time i got the same RMS,camera matrix,distortion coefficient as shown in attached image(output).but when i put this parameters in undist.py file that is give me blank image.. how to solve this problem?PLz help me...Thanks in advance.i have capture 8 image and one of the sample image of chessboard pattern shown in below image.This is my cal.py and undist.py file:cal.py#!/usr/bin/env pythonimport numpy as npimport cv2import cvimport osfrom common import splitfnUSAGE = ''' USAGE: calib.py [--save <filename>] [--debug <output path>] [--square_size] [<image mask>] '''if __name__ == '__main__': import sys, getopt from glob import glob camera_matrix = cv.CreateMat(3, 3, cv.CV_32FC1) dist_coefs = cv.CreateMat(4, 1, cv.CV_32FC1) args, img_mask = getopt.getopt(sys.argv[1:], '', ['save=', 'debug=', 'square_size=']) args = dict(args) img_mask = 'image*.jpg' img_names = glob(img_mask) debug_dir = args.get('--debug') square_size = float(args.get('--square_size', 1.0)) pattern_size = (9, 6) pattern_points = np.zeros( (np.prod(pattern_size), 3), np.float32 ) pattern_points[:,:2] = np.indices(pattern_size).T.reshape(-1, 2) pattern_points *= square_size obj_points = [] img_points = [] h, w = 0, 0 for fn in img_names: print 'processing %s...' % fn, img = cv2.imread(fn, 0) h, w = img.shape[:2] found, corners = cv2.findChessboardCorners(img, pattern_size) if found: term = ( cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_COUNT, 30, 0.1 ) cv2.cornerSubPix(img, corners, (5, 5), (-1, -1), term) if debug_dir: vis = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR) cv2.drawChessboardCorners(vis, pattern_size, corners, found) path, name, ext = splitfn(fn) cv2.imwrite('%s/%s_chess.png' % (debug_dir, name), vis) if not found: print 'chessboard not found' continue img_points.append(corners.reshape(-1, 2)) obj_points.append(pattern_points) print 'ok' rms, camera_matrix, dist_coefs, rvecs, tvecs = cv2.calibrateCamera(obj_points, img_points, (w, h)) print "RMS:", rms print "camera matrix:\n", camera_matrix print "distortion coefficients: ", dist_coefs.ravel() cv2.destroyAllWindows()undist.py#!/usr/bin/env pythonimport smtplibimport timeimport subprocessfrom email.MIMEMultipart import MIMEMultipartfrom email.MIMEBase import MIMEBasefrom email.MIMEText import MIMETextfrom email.MIMEImage import MIMEImageimport RPi.GPIO as GPIOimport Imageimport cv2import numpy as np# Define these once; use them twice!strFrom = '[email protected]'strTo = '[email protected]'#create email# Create the root message and fill in the from, to, and subj$msgRoot = MIMEMultipart()msgRoot['Subject'] = 'fisheye to normal image'msgRoot['From'] = strFrommsgRoot['To'] = strToGPIO.setmode(GPIO.BCM)GPIO.setup(4, GPIO.IN)print "press button to send email"GPIO.setup(4,GPIO.IN,pull_up_down=GPIO.PUD_UP)while True: input=GPIO.input(4) if input == False: print "button pressed" subprocess.Popen(["fswebcam","-r 640x480", "image4.jpg"]) time.sleep(5) # copy parameters to arrays K = np.array([[ 271.40850489,0,306.38705314],[0,271.08688021 , 234.03565551],[0,0,1]]) d = np.array( [ -3.55461489e-01 , 1.45402260e-01 , -1.33385142e-03 , 1.63603888e-04, -2.96650946e-02]) # just use first two terms (no translation) # read one of your images img = cv2.imread("image4.jpg") h, w = img.shape[:2] # undistort newcamera, roi = cv2.getOptimalNewCameraMatrix(K, d, (w,h), 0) newimg = cv2.undistort(img, K, d, None, newcamera) cv2.imwrite("original.jpg", img) cv2.imwrite("undistorted.jpg", newimg) # This example assumes the image is in the current directory #fp = open('image4.jpg', 'rb') #msgImage = MIMEImage(fp.read()) #fp.close() #msgRoot.attach(msgImage) # send mail #s = smtplib.SMTP('smtp.gmail.com',587) #s.starttls() #s.login('[email protected]' , 'password') #s.sendmail(strFrom, strTo, plt.show()) #s.close() print "Email sent" time.sleep(0.2)This is my input image:This is my output image: 解决方案 I will do an answer to summarize all the problems solved in the comments (this way the future readers do not have to read all of them).Follow the tutorial from here to have a better understanding of what you should do and which functions to use.Check that your camera matrix have the correct form:[ f_x s c_x 0 f_y c_y 0 0 1 ]the s is a skew value that I think in opencv it always gives 0.Make sure in every step that the images are loading correctly and that they are doing exactly what is intended (use imshow function to debug)This part of your codenewcamera, roi = cv2.getOptimalNewCameraMatrix(K, d, (w,h), 0)newimg = cv2.undistort(img, K, d, None, newcamera)is faulty. Why, well from the opencv documentation we have that:cv2.getOptimalNewCameraMatrix(cameraMatrix, distCoeffs, imageSize, alpha[, newImgSize[, centerPrincipalPoint]]) → retval, validPixROIandThis means that the new camera matrix also gives you a new valid size!! To be more specifically:But the undistort function does the initUndistortRectifyMap automatically.... and it doesn't have a way to pass the newImageSize from this function. So basically you have 2 options.Use your newcamera matrix, but instead of doing undistort, you should do everything manually.... this means that you must do initUndistortRectifyMap and remap using the new sizes and new camera matrix.Use the original camera matrix obtained in the calibrateCamera function. This way it will not have this zoom effect, but you may have some extra black pixels representing the areas that you may not see due to rectification.If not, it will always give you this zoom effect, because it will not show the invalid pixels (black pixels) of the undistorted areas. 这篇关于覆盆子pi:校准相机和图像的不失真的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持! 上岸,阿里云! 07-26 00:35