使用sobel算子高度映射到法线贴图

时间:2017-04-12 13:10:02

标签: c++ algorithm opencv

我正在尝试使用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)

基本上我找到了x渐变和y渐变的图像用Sobel()然后我做了渐变的产品但是我的结果就是这个;

enter image description here

来自此;

enter image description here

1 个答案:

答案 0 :(得分:0)

好的,我找到了解决方案,以防有人想要使用相同的算法;

            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());