Правильный способ искажения изображения рыбий глаз
Я сделал несколько примеров программ, которые удаляют искажения объектива на шахматной доске, такие как изображения рыбий глаз, и это работает хорошо, вот снимок экрана
Затем я хотел использовать шахматную доску "рыбий глаз" (правое изображение выше), чтобы убрать те же искажения линзы, но из реального изображения, и мне не повезло - искривление все еще остается на неискаженном изображении, поэтому я получил это вместо
код
void getObjectPoints(cv::Size, std::vector<std::vector<cv::Point3f>>&);
bool getImagePoints(cv::Mat&, cv::Size&, std::vector<std::vector<cv::Point2f>>&);
void runCalibration(cv::Mat& image, cv::Matx33d&, cv::Vec4d&);
cv::Mat removeFisheyeLensDist(cv::Mat&, cv::Matx33d&, cv::Vec4d&);
// ... definitions
void getObjectPoints(cv::Size patternSize, std::vector<std::vector<cv::Point3f>>& objectPoints)
{
const float squareSize = 0.0015f;
std::vector<cv::Point3f> knownBoardPositions;
for (int i = 0; i < patternSize.height; ++i)
{
for (int j = 0; j < patternSize.width; ++j)
{
knownBoardPositions.push_back(cv::Point3f(j*squareSize, i*squareSize, 0.0f));
}
}
if (knownBoardPositions.size() > 0)
objectPoints.push_back(knownBoardPositions);
}
bool getImagePoints(cv::Mat& image, cv::Size& patternSize, std::vector<std::vector<cv::Point2f>>& imagePoints)
{
bool patternFound = false;
while (!patternFound)
{
std::vector<cv::Point2f> corners;
for (int i = 7; i <= 30; ++i)
{
int w = i;
int h = i - 2;
patternFound = cv::findChessboardCorners(image, cv::Size(w, h), corners,
cv::CALIB_CB_ADAPTIVE_THRESH | cv::CALIB_CB_NORMALIZE_IMAGE);
if (patternFound)
{
patternSize.width = w;
patternSize.height = h;
imagePoints.push_back(corners);
break;
}
}
}
return patternFound;
}
void runCalibration(cv::Mat& image, cv::Matx33d& K, cv::Vec4d& D)
{
std::vector< std::vector<cv::Point2f> > imagePoints;
std::vector< std::vector<cv::Point3f> > objectPoints;
cv::Size patternSize;
bool patternFound = getImagePoints(image, patternSize, imagePoints);
if (patternFound)
{
getObjectPoints(patternSize, objectPoints);
std::vector<cv::Vec3d> rvecs;
std::vector<cv::Vec3d> tvecs;
cv::fisheye::calibrate(
objectPoints,
imagePoints,
image.size(),
K,
D,
rvecs,
tvecs,
cv::fisheye::CALIB_FIX_SKEW | cv::fisheye::CALIB_RECOMPUTE_EXTRINSIC
| cv::fisheye::CALIB_FIX_K1 | cv::fisheye::CALIB_FIX_K2
| cv::fisheye::CALIB_FIX_K3 | cv::fisheye::CALIB_FIX_K4
// cv::TermCriteria(3, 20, 1e-6)
);
}
}
cv::Mat removeFisheyeLensDist(cv::Mat& distorted, cv::Matx33d& K, cv::Vec4d& D)
{
cv::Mat undistorted;
cv::Matx33d newK = K;
cv::fisheye::undistortImage(distorted, undistorted, K, D, newK);
return undistorted;
}
int main(int argc, char* argv[])
{
cv::Mat chessBoardPattern = //..
cv::Mat distortedImage = //...
cv::imshow("distorted", distortedImage);
cv::Matx33d K; cv::Vec4d D;
runCalibration(chessBoardPattern, K, D);
cv::Mat undistoredImage = removeFisheyeLensDist(distortedImage, K, D);
cv::imshow("undistored", undistoredImage);
cv::waitKey(0);
return 0;
}
Поскольку я думаю, что изображение с башней имеет очень похожие кривизны, как шахматная доска справа, поэтому тот же самый образец должен был работать для изображения башни...
Что я там делаю не так? И почему он не фиксирует искажения объектива для изображения башни?
1 ответ
К сожалению ваше предположение
если изображения имеют одинаковую кривизну, то параметры камеры должны быть примерно одинаковыми, и поэтому я могу не искажать изображение "рыбий глаз" с рисунком на шахматной доске.
неправильно. Даже камеры одной модели будут иметь различия в фокусном расстоянии, геометрии и расположении объектива и т. Д., Которые необходимо калибровать индивидуально. Кроме того, во время использования камеры эти параметры могут изменяться из-за нагревания, вибрации и других эффектов (обычно это игнорируется на практике).
Чтобы не искажать изображение, не имея доступа к камере, все, что вы можете сделать, - это просто выбрать простую модель камеры "рыбий глаз" и попытаться оценить параметры вручную, пытаясь сделать прямые линии прямыми (например, используя графический интерфейс с ползунками для всех параметров). Это может быть утомительно, но я не знаю лучших вариантов. Кроме того, некоторые программы для редактирования изображений могут иметь инструменты для этого (если я правильно помню, GIMP делает)