distort2no_distort

本文介绍了一种基于OpenCV的畸变校正算法,通过非线性最小化计算,实现图像畸变点到非畸变点的精确映射。算法详细展示了如何利用DownhillSolver进行畸变参数求解,适用于相机畸变校正场景。
#include <iostream>
#include "opencv2/core.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"
#include <fstream>
using namespace cv;
using namespace std;
class DistortF :public cv::MinProblemSolver::Function
{
public:
    DistortF(double _distortU, double _distortV) : distortU(_distortU), distortV(_distortV)
    {

        Mat cameraMatrix = (Mat_<double>(3, 3) << 422.47278482, 0., 337.95105539, 0., 421.51185173, 230.2749964, 0., 0., 1.);
        inverseCameraMatrix = (cameraMatrix.colRange(0,3)).inv(DECOMP_LU);

        k1 = -0.36446607;
        k2 = 0.10597863;
        p1 = 0.00088569;
        p2 = -0.00112412;
        k3 = 0.;
        k4 =  0.;
        k5 = 0.;
        k6 = 0.;
        s1 = 0.;
        s2 =  0.;
        s3 = 0.;
        s4 = 0.;
        tauX =  0.;
        tauY =  0.;
    }
    int getDims() const { return 2; }
    double calc(const double* x)const{

        double undistortU = x[0];
        double undistortV = x[1];
        const double* ir = &inverseCameraMatrix(0, 0);
        //cout<< ir[0]<<endl;
        Mat cameraMatrix = (Mat_<double>(3, 3) << 422.47278482, 0, 337.95105539, 0, 421.51185173, 230.2749964, 0, 0, 1);
        const double* pA = (const double*)cameraMatrix.data;

        double Xd = undistortU * ir[0] + undistortV * ir[1] + ir[2], Yd = undistortU * ir[3] + undistortV * ir[4] + ir[5], Wd = undistortU * ir[6] + undistortV * ir[7] + ir[8];
        Wd = 1. / Wd;
        Xd = Xd * Wd;
        Yd = Yd * Wd;

        double Xd_2 = Xd*Xd, Yd_2 = Yd * Yd, r_2 = Xd_2 + Yd_2, _2XdYd = 2 * Xd * Yd;
        double kr = (1 + ((k3*r_2 + k2)*r_2 + k1)*r_2) / (1 + ((k6*r_2 + k5)*r_2 + k4)*r_2);
        double Xdd = (Xd*kr + p1*_2XdYd + p2*(r_2 + 2 * Xd_2) + s1*r_2 + s2*r_2*r_2);;
        double Ydd = (Yd*kr + p1*(r_2 + 2 * Yd_2) + p2*_2XdYd + s3*r_2 + s4*r_2*r_2);
        double Wdd = Wd;

        double distortU_d = pA[0] * Xdd + pA[1] * Ydd + pA[2] * Wdd;
        double distortV_d = pA[3] * Xdd + pA[4] * Ydd + pA[5] * Wdd;
        //printf("%f\n",sqrt((distortU - distortU_d) * (distortU - distortU_d) + (distortV - distortV_d) * (distortV - distortV_d)));
        return sqrt((distortU - distortU_d) * (distortU - distortU_d) + (distortV - distortV_d) * (distortV - distortV_d));
    }
private:
    double distortU, distortV;

    double k1;
    double k2;
    double p1;
    double p2;
    double k3;
    double k4;
    double k5;
    double k6;
    double s1;
    double s2;
    double s3;
    double s4;
    double tauX;
    double tauY;

    Mat_<double> inverseCameraMatrix;
};
string image_file = "images/4433.jpg";
int main() {
    cv::Mat image = cv::imread(image_file,0);   // 图像是灰度图,CV_8UC1
    int rows = image.rows, cols = image.cols;
    cv::Mat image_undistort = cv::Mat(rows, cols, CV_8UC1);
    ofstream oFile;
    oFile.open("/2.csv", ios::out | ios::trunc);
    oFile << "x_distortion" << "," << "y_distortion" << "," << "x_nodistor" << "," << "y_nodistor" << endl;
    for (int v_distorted = 0; v_distorted < rows; v_distorted++)
        for (int u_distorted = 0; u_distorted < cols; u_distorted++) {
            double u = 0, v = 0;
            cv::Ptr<cv::DownhillSolver> solver = cv::DownhillSolver::create();
            cv::Ptr<cv::MinProblemSolver::Function> ptr_F = cv::makePtr<DistortF>(u_distorted, v_distorted);//x,y为有畸变的点
            int lFaliedUndistCount=0;
            cv::Mat solution;
            solution= (cv::Mat_<double>(1, 2) << u_distorted, v_distorted);
            cv::Mat step;
            step= (cv::Mat_<double>(2, 1) << -0.5, -0.5);

            solver->setFunction(ptr_F);
            solver->setInitStep(step);
            float res=solver->minimize(solution);
            // cout<<res<<endl;
            u = solution.at<double>(0, 0);
            v = solution.at<double>(0, 1);
            if (u>= 0 && v >= 0 && u < cols && v < rows) {
                int a=0;
                a=image.at<uchar>((int) v_distorted, (int) u_distorted);
                image_undistort.at<uchar>((int)v, (int)u) =a;
            }
            oFile << u_distorted << "," << v_distorted<< "," << (int)u << "," << (int)v << endl;
        }

    cv::imshow("image undistorted", image_undistort);
    cv::waitKey();
    return  0;
}

对应的cmake.txt

cmake_minimum_required(VERSION 3.10)
project(untitled8)

set(CMAKE_CXX_STANDARD 11)

add_executable(untitled8 main.cpp)
target_link_libraries(untitled8 opencv_core opencv_highgui opencv_imgproc opencv_imgcodecs )

必须opencv3,这个是3.3.0

 

单个点的:

#include <iostream>
#include "opencv2/core.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/videoio.hpp"
#include<time.h>
#define UNDISTORT_FAILED_THRES 0.1
using namespace cv;
using namespace std;
//非线性最小化计算函数
class DistortF :public cv::MinProblemSolver::Function
{
public:
    DistortF(double _distortU, double _distortV) : distortU(_distortU), distortV(_distortV)
    {

        Mat cameraMatrix = (Mat_<double>(3, 3) << 422.47278482, 0., 337.95105539, 0., 421.51185173, 230.2749964, 0., 0., 1.);
        inverseCameraMatrix = (cameraMatrix.colRange(0,3)).inv(DECOMP_LU);

        k1 = -0.36446607;
        k2 = 0.10597863;
        p1 = 0.00088569;
        p2 = -0.00112412;
        k3 = 0.;
        k4 =  0.;
        k5 = 0.;
        k6 = 0.;
        s1 = 0.;
        s2 =  0.;
        s3 = 0.;
        s4 = 0.;
        tauX =  0.;
        tauY =  0.;
    }
    int getDims() const { return 2; }
    double calc(const double* x)const{

        double undistortU = x[0];
        double undistortV = x[1];
        const double* ir = &inverseCameraMatrix(0, 0);
        //cout<< ir[0]<<endl;
        Mat cameraMatrix = (Mat_<double>(3, 3) << 422.47278482, 0, 337.95105539, 0, 421.51185173, 230.2749964, 0, 0, 1);
        const double* pA = (const double*)cameraMatrix.data;

        double Xd = undistortU * ir[0] + undistortV * ir[1] + ir[2], Yd = undistortU * ir[3] + undistortV * ir[4] + ir[5], Wd = undistortU * ir[6] + undistortV * ir[7] + ir[8];
        Wd = 1. / Wd;
        Xd = Xd * Wd;
        Yd = Yd * Wd;

        double Xd_2 = Xd*Xd, Yd_2 = Yd * Yd, r_2 = Xd_2 + Yd_2, _2XdYd = 2 * Xd * Yd;
        double kr = (1 + ((k3*r_2 + k2)*r_2 + k1)*r_2) / (1 + ((k6*r_2 + k5)*r_2 + k4)*r_2);
        double Xdd = (Xd*kr + p1*_2XdYd + p2*(r_2 + 2 * Xd_2) + s1*r_2 + s2*r_2*r_2);;
        double Ydd = (Yd*kr + p1*(r_2 + 2 * Yd_2) + p2*_2XdYd + s3*r_2 + s4*r_2*r_2);
        double Wdd = Wd;

        double distortU_d = pA[0] * Xdd + pA[1] * Ydd + pA[2] * Wdd;
        double distortV_d = pA[3] * Xdd + pA[4] * Ydd + pA[5] * Wdd;
        //printf("%f\n",sqrt((distortU - distortU_d) * (distortU - distortU_d) + (distortV - distortV_d) * (distortV - distortV_d)));
        return sqrt((distortU - distortU_d) * (distortU - distortU_d) + (distortV - distortV_d) * (distortV - distortV_d));
    }
private:
    double distortU, distortV;

    double k1;
    double k2;
    double p1;
    double p2;
    double k3;
    double k4;
    double k5;
    double k6;
    double s1;
    double s2;
    double s3;
    double s4;
    double tauX;
    double tauY;

    Mat_<double> inverseCameraMatrix;
};
//输入畸变图中的x,y点
int main() {
    double x,y;
    cout << "Input x: ";
    cin >> x;
    cout << "Input y: ";
    cin >> y;
    clock_t start,finish;
    double totaltime;
    start=clock();
    cv::Ptr<cv::DownhillSolver> solver = cv::DownhillSolver::create();
    cv::Ptr<cv::MinProblemSolver::Function> ptr_F = cv::makePtr<DistortF>(x, y);//x,y为有畸变的点
    int lFaliedUndistCount=0;
    cv::Mat solution;
    solution= (cv::Mat_<double>(1, 2) << x, y);
    cv::Mat step;
    step= (cv::Mat_<double>(2, 1) << -0.5, -0.5);

    solver->setFunction(ptr_F);
    solver->setInitStep(step);
    float res=solver->minimize(solution);
    // cout<<res<<endl;
    double u = solution.at<double>(0, 0);
    double v = solution.at<double>(0, 1);
    finish=clock();
    totaltime=(double)(finish-start)/CLOCKS_PER_SEC;
    cout<<"\n此程序的运行时间为"<<totaltime<<"秒!"<<endl;
    cout<<int(u)<<endl;
    cout<<int(v)<<endl;
}

 

../../src/aqi/aecns/main/tpaec3ns3/aqi_tpaecns.c:59:23: error: ‘D_INPUT_FRAME_MAX_LEN’ undeclared here (not in a function) 59 | short aec_out_buf[D_INPUT_FRAME_MAX_LEN]; | ^~~~~~~~~~~~~~~~~~~~~ ../../src/aqi/aecns/main/tpaec3ns3/aqi_tpaecns.c: In function ‘aecns_ptz_callback’: ../../src/aqi/aecns/main/tpaec3ns3/aqi_tpaecns.c:124:36: error: ‘AEC_CONTEXT’ {aka ‘struct AEC_CONTEXT’} has no member named ‘den’ 124 | gp_aecns_context->p_aec_context->den->motor_state = motor_type; | ^~ ../../src/aqi/aecns/main/tpaec3ns3/aqi_tpaecns.c: In function ‘aecns_init’: ../../src/aqi/aecns/main/tpaec3ns3/aqi_tpaecns.c:411:71: warning: passing argument 2 of ‘aec_module_init’ makes pointer from integer without a cast [-Wint-conversion] 411 | if (ERROR == aec_module_init(gp_aecns_context->p_aec_context, sample_rate, args->use_timestamp, &g_aec3_sys_config)) | ^~~~~~~~~~~ | | | int32_t {aka int} In file included from ../../src/aqi/aecns/main/tpaec3ns3/aqi_tpaecns.c:8: ../../src/aqi/aecns/aec/aec/audio_aec.h:224:67: note: expected ‘AUDIO_COMMON_CONTEXT *’ {aka ‘struct AUDIO_COMMON_CONTEXT *’} but argument is of type ‘int32_t’ {aka ‘int’} 224 | S32 aec_module_init(AEC_CONTEXT *p_context, AUDIO_COMMON_CONTEXT *far_common_context, | ~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~ ../../src/aqi/aecns/main/tpaec3ns3/aqi_tpaecns.c:411:88: warning: passing argument 3 of ‘aec_module_init’ makes pointer from integer without a cast [-Wint-conversion] 411 | if (ERROR == aec_module_init(gp_aecns_context->p_aec_context, sample_rate, args->use_timestamp, &g_aec3_sys_config)) | ~~~~^~~~~~~~~~~~~~~ | | | int In file included from ../../src/aqi/aecns/main/tpaec3ns3/aqi_tpaecns.c:8: ../../src/aqi/aecns/aec/aec/audio_aec.h:225:27: note: expected ‘AUDIO_COMMON_CONTEXT *’ {aka ‘struct AUDIO_COMMON_CONTEXT *’} but argument is of type ‘int’ 225 | AUDIO_COMMON_CONTEXT *near_common_context, S32 sample_rate, int use_timestamp); | ~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~ ../../src/aqi/aecns/main/tpaec3ns3/aqi_tpaecns.c:411:105: warning: passing argument 4 of ‘aec_module_init’ makes integer from pointer without a cast [-Wint-conversion] 411 | if (ERROR == aec_module_init(gp_aecns_context->p_aec_context, sample_rate, args->use_timestamp, &g_aec3_sys_config)) | ^~~~~~~~~~~~~~~~~~ | | | AEC3_SYS_CONFIG * {aka struct _AEC3_SYS_CONFIG *} In file included from ../../src/aqi/aecns/main/tpaec3ns3/aqi_tpaecns.c:8: ../../src/aqi/aecns/aec/aec/audio_aec.h:225:52: note: expected ‘int32_t’ {aka ‘int’} but argument is of type ‘AEC3_SYS_CONFIG *’ {aka ‘struct _AEC3_SYS_CONFIG *’} 225 | AUDIO_COMMON_CONTEXT *near_common_context, S32 sample_rate, int use_timestamp); ../../src/aqi/aecns/main/tpaec3ns3/aqi_tpaecns.c:411:22: error: too few arguments to function ‘aec_module_init’ 411 | if (ERROR == aec_module_init(gp_aecns_context->p_aec_context, sample_rate, args->use_timestamp, &g_aec3_sys_config)) | ^~~~~~~~~~~~~~~ In file included from ../../src/aqi/aecns/main/tpaec3ns3/aqi_tpaecns.c:8: ../../src/aqi/aecns/aec/aec/audio_aec.h:224:5: note: declared here 224 | S32 aec_module_init(AEC_CONTEXT *p_context, AUDIO_COMMON_CONTEXT *far_common_context, | ^~~~~~~~~~~~~~~ ../../src/aqi/aecns/main/tpaec3ns3/aqi_tpaecns.c: In function ‘aecns_process’: ../../src/aqi/aecns/main/tpaec3ns3/aqi_tpaecns.c:625:36: error: ‘AEC_CONTEXT’ {aka ‘struct AEC_CONTEXT’} has no member named ‘st’ 625 | gp_aecns_context->p_aec_context->st->aec_enable = aec_enable; | ^~ ../../src/aqi/aecns/main/tpaec3ns3/aqi_tpaecns.c:627:36: error: ‘AEC_CONTEXT’ {aka ‘struct AEC_CONTEXT’} has no member named ‘sdata_len’ 627 | gp_aecns_context->p_aec_context->sdata_len = sdata_len; | ^~ ../../src/aqi/aecns/main/tpaec3ns3/aqi_tpaecns.c:628:36: error: ‘AEC_CONTEXT’ {aka ‘struct AEC_CONTEXT’} has no member named ‘mic_buf_ptr’ 628 | gp_aecns_context->p_aec_context->mic_buf_ptr = (S16 *)(args->mic_buf); | ^~ ../../src/aqi/aecns/main/tpaec3ns3/aqi_tpaecns.c:631:40: error: ‘AEC_CONTEXT’ {aka ‘struct AEC_CONTEXT’} has no member named ‘spk_buf_ptr’ 631 | gp_aecns_context->p_aec_context->spk_buf_ptr = (S16 *)(args->spk_buf); | ^~ ../../src/aqi/aecns/main/tpaec3ns3/aqi_tpaecns.c:633:47: error: ‘AEC_CONTEXT’ {aka ‘struct AEC_CONTEXT’} has no member named ‘spk_buf_zero’ 633 | memset(gp_aecns_context->p_aec_context->spk_buf_zero, 0, 2 * sizeof(short) * D_AEC_FRAME_LEN_WB); | ^~ ../../src/aqi/aecns/main/tpaec3ns3/aqi_tpaecns.c:633:86: error: ‘D_AEC_FRAME_LEN_WB’ undeclared (first use in this function) 633 | memset(gp_aecns_context->p_aec_context->spk_buf_zero, 0, 2 * sizeof(short) * D_AEC_FRAME_LEN_WB); | ^~~~~~~~~~~~~~~~~~ ../../src/aqi/aecns/main/tpaec3ns3/aqi_tpaecns.c:633:86: note: each undeclared identifier is reported only once for each function it appears in ../../src/aqi/aecns/main/tpaec3ns3/aqi_tpaecns.c:634:40: error: ‘AEC_CONTEXT’ {aka ‘struct AEC_CONTEXT’} has no member named ‘spk_buf_ptr’ 634 | gp_aecns_context->p_aec_context->spk_buf_ptr = gp_aecns_context->p_aec_context->spk_buf_zero; | ^~ ../../src/aqi/aecns/main/tpaec3ns3/aqi_tpaecns.c:634:87: error: ‘AEC_CONTEXT’ {aka ‘struct AEC_CONTEXT’} has no member named ‘spk_buf_zero’ 634 | gp_aecns_context->p_aec_context->spk_buf_ptr = gp_aecns_context->p_aec_context->spk_buf_zero; | ^~ ../../src/aqi/aecns/main/tpaec3ns3/aqi_tpaecns.c:636:36: error: ‘AEC_CONTEXT’ {aka ‘struct AEC_CONTEXT’} has no member named ‘out_buf_ptr’ 636 | gp_aecns_context->p_aec_context->out_buf_ptr = gp_aecns_context->aec_out_buf; | ^~ ../../src/aqi/aecns/main/tpaec3ns3/aqi_tpaecns.c:648:41: error: ‘AEC_CONTEXT’ {aka ‘struct AEC_CONTEXT’} has no member named ‘aec3_live_support_switch’ 648 | if ((gp_aecns_context->p_aec_context->aec3_live_support_switch || aec_enable) && (gp_aecns_context->p_aec_context->aec3_dt_support_switch || !(aec_enable))) | ^~ ../../src/aqi/aecns/main/tpaec3ns3/aqi_tpaecns.c:648:118: error: ‘AEC_CONTEXT’ {aka ‘struct AEC_CONTEXT’} has no member named ‘aec3_dt_support_switch’ 648 | if ((gp_aecns_context->p_aec_context->aec3_live_support_switch || aec_enable) && (gp_aecns_context->p_aec_context->aec3_dt_support_switch || !(aec_enable))) | ^~ ../../src/aqi/aecns/main/tpaec3ns3/aqi_tpaecns.c:664:48: error: ‘AEC_CONTEXT’ {aka ‘struct AEC_CONTEXT’} has no member named ‘st’ 664 | gp_aecns_context->p_aec_context->st->speaker_distort = 1; | ^~ ../../src/aqi/aecns/main/tpaec3ns3/aqi_tpaecns.c:668:48: error: ‘AEC_CONTEXT’ {aka ‘struct AEC_CONTEXT’} has no member named ‘st’ 668 | gp_aecns_context->p_aec_context->st->speaker_distort = 0; | ^~ ../../src/aqi/aecns/main/tpaec3ns3/aqi_tpaecns.c:676:154: error: ‘AEC_CONTEXT’ {aka ‘struct AEC_CONTEXT’} has no member named ‘vad_for_agc_enable’ 676 | agc_process(gp_aecns_context->p_agc_context, 0, gp_aecns_context->aec_out_buf, gp_aecns_context->agc_out_buf, gp_aecns_context->p_aec_context->vad_for_agc_enable, gp_aecns_context->p_aec_context->vad_list, sdata_len); | ^~ ../../src/aqi/aecns/main/tpaec3ns3/aqi_tpaecns.c:676:207: error: ‘AEC_CONTEXT’ {aka ‘struct AEC_CONTEXT’} has no member named ‘vad_list’ 676 | agc_process(gp_aecns_context->p_agc_context, 0, gp_aecns_context->aec_out_buf, gp_aecns_context->agc_out_buf, gp_aecns_context->p_aec_context->vad_for_agc_enable, gp_aecns_context->p_aec_context->vad_list, sdata_len); | ^~ ../../src/aqi/aecns/main/tpaec3ns3/aqi_tpaecns.c:693:40: error: ‘AEC_CONTEXT’ {aka ‘struct AEC_CONTEXT’} has no member named ‘st’ 693 | gp_aecns_context->p_aec_context->st->old_aec_enable = aec_enable; /* Records the AEC switch status of the previous frame */ | ^~ ../../src/aqi/aecns/main/tpaec3ns3/aqi_tpaecns.c:699:78: error: ‘AEC_CONTEXT’ {aka ‘struct AEC_CONTEXT’} has no member named ‘mic_buf_ptr’ 699 | memcpy(gp_aecns_context->aec_out_buf, gp_aecns_context->p_aec_context->mic_buf_ptr, sizeof(short) * gp_aecns_context->p_aec_context->sdata_len); | ^~ ../../src/aqi/aecns/main/tpaec3ns3/aqi_tpaecns.c:699:140: error: ‘AEC_CONTEXT’ {aka ‘struct AEC_CONTEXT’} has no member named ‘sdata_len’ 699 | memcpy(gp_aecns_context->aec_out_buf, gp_aecns_context->p_aec_context->mic_buf_ptr, sizeof(short) * gp_aecns_context->p_aec_context->sdata_len); | ^~ ../../src/aqi/aecns/main/tpaec3ns3/aqi_tpaecns.c:701:40: error: ‘AEC_CONTEXT’ {aka ‘struct AEC_CONTEXT’} has no member named ‘st’ 701 | gp_aecns_context->p_aec_context->st->old_aec_enable = aec_enable; 这是什么报错
09-05
内容概要:本文系统介绍了算术优化算法(AOA)的基本原理、核心思想及Python实现方法,并通过图像分割的实际案例展示了其应用价值。AOA是一种基于种群的元启发式算法,其核心思想来源于四则运算,利用乘除运算进行全局勘探,加减运算进行局部开发,通过数学优化器加速函数(MOA)和数学优化概率(MOP)动态控制搜索过程,在全局探索与局部开发之间实现平衡。文章详细解析了算法的初始化、勘探与开发阶段的更新策略,并提供了完整的Python代码实现,结合Rastrigin函数进行测试验证。进一步地,以Flask框架搭建前后端分离系统,将AOA应用于图像分割任务,展示了其在实际工程中的可行性与高效性。最后,通过收敛速度、寻优精度等指标评估算法性能,并提出自适应参数调整、模型优化和并行计算等改进策略。; 适合人群:具备一定Python编程基础和优化算法基础知识的高校学生、科研人员及工程技术人员,尤其适合从事人工智能、图像处理、智能优化等领域的从业者;; 使用场景及目标:①理解元启发式算法的设计思想与实现机制;②掌握AOA在函数优化、图像分割等实际问题中的建模与求解方法;③学习如何将优化算法集成到Web系统中实现工程化应用;④为算法性能评估与改进提供实践参考; 阅读建议:建议读者结合代码逐行调试,深入理解算法流程中MOA与MOP的作用机制,尝试在不同测试函数上运行算法以观察性能差异,并可进一步扩展图像分割模块,引入更复杂的预处理或后处理技术以提升分割效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值