【问题标题】:height map to normal map with sobel operator使用 sobel 运算符将高度图转换为法线图
【发布时间】:2017-09-08 07:00:55
【问题描述】:

我正在尝试使用 sobel 运算符将高度图转换为法线图,并使用一些 opencv 函数这是我的代码;

    cv::Mat src = cv::imread("C:/Users/Cihan/Desktop/aa.png");
    cv::Mat src_gray;
    GaussianBlur(src, src, cv::Size(3, 3), 0, 0, 4);
    cvtColor(src, src_gray, CV_BGR2GRAY);

    cv::Mat grad_x;
    cv::Mat grad_y;
    int ddepth = CV_16S;
    int scale = 1;
    int delta = 0;
    cv::Sobel(src_gray, grad_x, ddepth, 1, 0, 3, scale, delta, 4);
    cv::Sobel(src_gray, grad_y, ddepth, 0, 1, 3, scale, delta, 4);
    //cv::imwrite("C:/Users/Cihan/Desktop/kk.png", grad_x);

    cv::Mat abs_grad_x;
    cv::Mat abs_grad_y;
    cv::convertScaleAbs(grad_x, abs_grad_x);
    cv::convertScaleAbs(grad_y, abs_grad_y);



    cv::Mat imgNew(src.size().height, src.size().width, CV_8UC3);
    for (int x = 0; x < src.size().height; ++x) {
        for (int y = 0; y < src.size().width; ++y) {

            float pixel_x = abs_grad_x.at<uint8_t>(x, y);
            float pixel_y = abs_grad_y.at<uint8_t>(x, y);

            Vec3f dx = Vec3f{ pixel_x, 0.0f,0.0f};
            dx.normalize();


            Vec3f dy = Vec3f{ 0.0f, pixel_y,0.0f};
            dy.normalize();

            Vec3f nm = dx.cross(dy);
            nm.normalize();
            nm = (nm * 127.5f) + Vec3f{ 128.0f, 128.0f, 128.0f };



            auto& imgRGB = imgNew.at<cv::Vec3b>(x, y);
            imgRGB[2] = static_cast<uint8_t>(nm.x());
            imgRGB[1] = static_cast<uint8_t>(nm.y());
            imgRGB[0] = static_cast<uint8_t>(nm.z());

    }

}


cv::imwrite("C:/Users/Cihan/Desktop/tt.png", imgNew)

基本上我用 Sobel() 找到图像的 x 梯度和 y 梯度,然后我做梯度的叉积,但我的结果是这样的;

从此;

【问题讨论】:

  • 看起来你只是在垂直过滤,而不是水平过滤。
  • @CihanKara 你如何期望 ` Vec3f dx = Vec3f{ pixel_x, 0.0f,0.0f};dx.normalize();` 给你提供除 (0,0,0) 或 @987654325 之外的其他东西@?

标签: c++ algorithm opencv


【解决方案1】:

好吧,如果有人想使用相同的算法,我已经找到了解决方案;

            cv::Mat src = cv::imread("C:/Users/Cihan/Desktop/aa.png");
            cv::Mat src_gray;
            cvtColor(src, src_gray, CV_BGR2GRAY);

            cv::Mat grad_x;
            cv::Mat grad_y;
            int ddepth = CV_16S;
            int scale = 1;
            int delta = 0;
            cv::Sobel(src_gray, grad_x, ddepth, 1, 0, 3, scale, delta,1);

            //cv::Mat M;
            //M = src_gray.getRotationMatrix2D((cols / 2, rows / 2), 90, 1)

            cv::Sobel(src_gray, grad_y, ddepth, 0, 1, 3, scale, delta,1);



            cv::Mat abs_grad_x;
            cv::Mat abs_grad_y;
            cv::convertScaleAbs(grad_x, abs_grad_x,0.125,127.5);
            cv::convertScaleAbs(grad_y, abs_grad_y,0.125,127.5);
            cv::imwrite("C:/Users/Cihan/Desktop/kk.png", abs_grad_x);
            cv::imwrite("C:/Users/Cihan/Desktop/ll.png", abs_grad_y);


            cv::Mat imgNew(src.size().height, src.size().width, CV_8UC3);
            for (int y =0; y < src.size().height; ++y) {
                for (int x=0; x < src.size().width; ++x) {



                    float pixel_x = ((static_cast<float>
                  (abs_grad_x.at<uint8_t>(x, y))*2.0f)/255.0f)-1.0f;
                    float pixel_y = -(((static_cast<float>
                   (abs_grad_y.at<uint8_t>(x, y))*2.0f)/255.0f)-1.0f);


                    Vec3f dx = Vec3f{ 1.0f, 0.0f,pixel_x };
                    dx.normalize();



                    Vec3f dy = Vec3f{ 0.0f, 1.0f,pixel_y };
                    dy.normalize();


                    Vec3f nm = dx.cross(dy);
                    nm.normalize();
                    nm = (nm * 128.0f) + Vec3f{ 128.0f, 128.0f, 128.0f };




                    auto& imgRGB = imgNew.at<cv::Vec3b>(x, y);
                    imgRGB[2] = static_cast<uint8_t>(nm.x());
                    imgRGB[1] = static_cast<uint8_t>(nm.y());
                    imgRGB[0] = static_cast<uint8_t>(nm.z());

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-11-18
    • 1970-01-01
    • 1970-01-01
    • 2015-04-30
    • 2016-02-17
    • 2015-09-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多