2016-09-01 3 views
0

Я следую за this tutorial, чтобы калибровать мою камеру (с некоторым объективом) на малине Pi, но используя circular pattern вместо шахматной доски. Проблема в том, что получившееся неискаженное изображение сжато и не заполнено, и когда я получаю все сокращения от кода, он выглядит как правая часть this (обычно это еще хуже). Вопрос в том, можно ли что-то сделать с кодом, чтобы он выдавал картинку вроде the example from the tutorial. Должен ли я использовать шаблон шахматной доски для этого?Калибровка камеры с круговым рисунком

Мой код:

import numpy as np 
import cv2 
from picamera.array import PiRGBArray 
from picamera import PiCamera 
import time 



# termination criteria 
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001) 

# prepare object points, like (0,0,0), (1,0,0), (2,0,0) ....,(6,5,0) 
#objp = np.zeros((4*11,3), np.float32) 
#objp[:,:2] = np.mgrid[0:7,0:6].T.reshape(-1,2) 
objp=np.array([[0,0,0],[1,0,0],[2,0,0],[3,0,0],[0.5,0.5,0],[1.5,0.5,0],[2.5,0.5,0],[3.5,0.5,0]]) 
for y in range(2,11): 
     for x in range(4): 
       objp=np.append(objp,[np.array([objp[4*(y-2)+x][0],objp[4*(y-2)+x][1]+1,0])],axis=0) 

# Arrays to store object points and image points from all the images. 
objpoints = [] # 3d point in real world space 
imgpoints = [] # 2d points in image plane. 

#images = glob.glob('pict*.jpg') 

# initialize the camera and grab a reference to the raw camera capture 
camera = PiCamera() 
camera.resolution = (640, 480) 
camera.framerate = 32 
rawCapture = PiRGBArray(camera, size=(640, 480)) 

# allow the camera to warmup 
time.sleep(0.1) 
ret0=[] 
j=0 
for i,frame in enumerate(camera.capture_continuous(rawCapture, format="bgr", use_video_port=True)): 
    image = frame.array 
    img=image[::-1] 
    gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) 

    # Find the chess board corners 
    ret, corners = cv2.findCirclesGrid(gray, (4,11),None,flags=cv2.CALIB_CB_ASYMMETRIC_GRID) 
    # If found, add object points, image points (after refining them) 
    if ret == True and np.sum(np.int32(ret0))<15 and not i%10: 
     ret0.append(ret) 
     print("{} more for proper calibration".format(15-np.sum(np.int32(ret0)))) 
     objpoints.append(objp.astype('float32')) 

     corners2 = cv2.cornerSubPix(gray,corners,(11,11),(-1,-1),criteria) 
     imgpoints.append(corners2.reshape(-1, 2).astype('float32')) 

     # Draw and display the corners 
     img = cv2.drawChessboardCorners(img.copy(), (4,11), corners2,ret) 
     cv2.imshow('img',img) 
     cv2.waitKey(1000) 
     cv2.imwrite('cal{}.jpg'.format(j),img) 
     j+=1 
     rawCapture.truncate(0) 
    elif np.sum(np.int32(ret0))<15: 
     cv2.imshow('img',img) 
     cv2.waitKey(1) 
     rawCapture.truncate(0) 
    else: 
     rawCapture.truncate(0) 
     break 

dist = np.array([-0.13615181, 0.53005398, 0, 0, 0]) # no translation 
ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, gray.shape[::-1],None,None) 

h, w = img.shape[:2] 
newcameramtx, roi=cv2.getOptimalNewCameraMatrix(mtx,dist,(w,h),1,(w,h)) 

np.savetxt('newcameramtx.out',newcameramtx) 
np.savetxt('mtx.out',mtx) 
np.savetxt('dist.out',dist) 

#img=cv2.imread('pict1.jpg') 
# undistort 
dst = cv2.undistort(img, mtx, dist, None, newcameramtx) 

# crop the image 
x,y,w,h = roi 
dst = dst[y:y+h, x:x+w] 
cv2.imwrite('calibresult.png',dst) 

cv2.imshow('undistorted',dst) 
cv2.waitKey(0)&0xFF 

cv2.destroyAllWindows() 

UPD: Я пытался калибровки с рисунком шахматной доски, и программа даже не хочет признать картину! Вот примеры с обнаруженным круговой схеме: oneother one moreenter image description here

Так что программа якобы обнаруживает круги, но не так идеально, как бы хотелось.

+0

Я использовал шахматную доску для калибровки, она работает довольно хорошо, проблема, которую вы испытываете с круговой моделью, заключается в том, что вам нужно определить радиус при использовании перекрестков, достаточно хорошо определить, чтобы алгоритм мог искать изменение черного цвета в 4 направлениях (2 черных и 2 белых квадрата), поэтому я думаю, что это будет работать лучше. PS: сделал это с помощью C++ и не имею в виду, как это сделать в python, так что извините, что не может помочь вам с кодом! – Engine

+0

Вы пытаетесь вычислить положение подпикселя ваших позиций в центре круга с помощью 'cv2.cornerSubPix', но у вас нет углов, поэтому это может привести к проблемам. И почему бы не использовать шахматную доску? Он инвариантен относительно искажения смещения. Являются ли ваши обнаруженные центральные позиции правильными или абсолютно ошибочными? Можете ли вы опубликовать изображение нарисованных «углов»;) – PSchn

+0

@PSchn, обновил мой вопрос – Oresto

ответ

2

Вы можете попытаться настроить параметры детектора blob. По умолчанию findCirclesGrid использует SimpleBlobDetector. Поэтому постарайтесь, чтобы желчный параметры, например:

params = cv2.SimpleBlobDetector_Params() 
params.minArea = 10; 
params.minDistBetweenBlobs = 5; 
detector = cv2.SimpleBlobDetector_create(params) 

, а затем передать его в findCirclesGrid:

cv2.findCirclesGrid(gray, (4,11),None,flags=cv2.CALIB_CB_ASYMMETRIC_GRID,detector) 

Additionaly вы можете попробовать использовать cv2.CALIB_CB_ASYMMETRIC_GRID + cv2.CALIB_CB_CLUSTERING

Для получения дополнительной информации о SimpleBlobDetector и его параметры см. this tutrial.

+0

Должен ли я изменить 'cv2.cornerSubPix' на что-то еще или, может быть, даже удалить эту строку и все, что с ней связано все? – Oresto

+0

Если вы хотите использовать только шаблон окружности, вы можете удалить эту строку. – PSchn

+0

ОК, так что это сработало, когда я записал 'ret, corners = cv2.findCirclesGrid (серый, (4,11), None, flags = cv2.CALIB_CB_ASYMMETRIC_GRID, blobDetector = детектор)'. Когда я использовал приведенные матрицы в другой программе, он закричал, что строки с 'x, y, w, h = roi; frame = frame [y: y + h, x: x + w] 'обрезал весь кадр, и из-за этого функция 'cv2.imwrite()' ничего не могла написать, но когда я прокомментирую эти строки, все в порядке (по крайней мере, я надеюсь, что это так). Так что спасибо – Oresto

Смежные вопросы