前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >图像凹凸算法(代码全)

图像凹凸算法(代码全)

作者头像
用户3578099
发布2020-11-19 17:25:43
1.6K0
发布2020-11-19 17:25:43
举报
文章被收录于专栏:AI科技时讯

https://www.cnblogs.com/pingwen/p/12503047.html

一、图像挤压特效

1、原理

图像压效果本质的图像坐标的非线性变换,将图像向内挤压,挤压的过程产生压缩变形,从而形成的效果。

挤压效果的实现是通过极坐标的形式,设图像中心为O(x,y),某点距离中心O的距离为半径R,非线性方式改变半径R但不改变点的方向,就构成了图像挤压。也可以自定义加压中心点,计算半径方式相同。

图像像素变换倍率使用 y=sqrt(x)。

图像上点P与图像中心O的距离为R,图像挤压就是P点坐标映射到OP直线上的点R2位置,其中| OR2 |=sqrt(OP)*ratio。

2、实现

代码语言:javascript
复制
void Pinch(Mat& img, Mat& dst, int degree)
{
    if (degree < 1) degree = 1;
    if (degree > 32) degree = 32;

    if (dst.empty())
        dst.create(img.rows, img.cols, img.type());
    dst = cv::Scalar::all(0);

    int chns = img.channels();
    int height = img.rows;
    int width = img.cols;

    int midX = width / 2;
    int midY = height / 2;
    int i, j, k;
    int X, Y, offsetX, offsetY;
    double radian, radius;  //弧和半径

    for (i = 0; i < height; i++)
    {
        for (j = 0; j < width; j++)
        {
            offsetX = j - midX;
            offsetY = i - midY;

            radian = atan2((double)offsetY, (double)offsetX);

            // 半径
            radius = sqrtf((float)(offsetX*offsetX + offsetY * offsetY));
            radius = sqrtf(radius)*degree;

            X = (int)(radius*cos(radian)) + midX;
            Y = (int)(radius*sin(radian)) + midY;

            if (X < 0) X = 0;
            if (X >= width) X = width - 1;
            if (Y < 0) Y = 0;
            if (Y >= height) Y = height - 1;

            for (k = 0; k < chns; k++)
            {
                dst.at<Vec3b>(i, j)[k] = img.at<Vec3b>(Y, X)[k];
            }
        }
    }
}

Mat src_img;
Mat dst_img;
int rato = 15;

void call_back(int, void*)
{
    Pinch(src_img, dst_img, rato);
    imshow("Pinch图", dst_img);
}

int main() {

    src_img = imread("D:\\WORK\\5.OpenCV\\LeanOpenCV\\pic_src\\pic18.bmp");
    imshow("原图", src_img);

    Pinch(src_img, dst_img, rato);
    imshow("Pinch图", dst_img);

    namedWindow("Pinch图");
    createTrackbar("Pinch倍率", "Pinch图", &rato, 50, call_back);
    call_back(rato, 0);

    waitKey(0);
}

3、测试效果

测试1:

测试2:不同倍率下棋盘格的挤压效果。

二、哈哈镜特效

1、原理

图像坐标的非线性变换,实现k的根号与k的比值,sqrt(k)/k, 当k为1时总倍率为1,当k小于1时,总倍率为渐变倍率。

2、实现

代码语言:javascript
复制
void Pinch(Mat& img, Mat& dst, int x, int y, int degree)
{
    if (dst.empty())
        dst.create(img.rows, img.cols, img.type());

    dst = cv::Scalar::all(0);
    cout << "x,y " << x << " " << y << endl;

    int chns = img.channels();
    int height = img.rows;
    int width = img.cols;

    midX = x;
    midY = y; 
    int R = 100;

    int i, j, k;
    int X, Y, offsetX, offsetY;
    double radian, radius;  //弧和半径

    for (i = 0; i < height; i++)
    {
        for (j = 0; j < width; j++)
        {
            offsetX = j - midX;
            offsetY = i - midY;
             radian = atan2((double)offsetY, (double)offsetX);

            // 半径
            radius = sqrtf((float)(offsetX*offsetX + offsetY * offsetY));
            if (radius <= R &&  radius > 1) {
                float k = sqrtf(radius/R) * radius / R * degree;
                X = (int)( cos(radian) * k) + midX;
                Y = (int)( sin(radian) * k) +  midY;

                if (X < 0) X = 0;
                if (X >= width) X = width - 1;
                if (Y < 0) Y = 0;
                if (Y >= height) Y = height - 1;

                for (k = 0; k < chns; k++)
                {
                    dst.at<Vec3b>(i, j)[k] = img.at<Vec3b>(Y, X)[k];
                }
            }
            else 
            {
                for (k = 0; k < chns; k++)
                {
                    dst.at<Vec3b>(i, j)[k] = img.at<Vec3b>(i, j)[k];
                }
            }
        }
    }

    cout << " midX, midY " << midX << " " << midY << endl;
}

3、测试效果

测试1:哈哈镜效果

测试2:大倍率呈现潜望镜效果。

测试3:

三、图像扭曲

对图像的像素坐标进行正弦变换,映射到对应坐标就完成了图像扭曲。关键代码如下:

代码语言:javascript
复制
for (int j = 0; j < width; j++)
{
    double temp =  degree * sin(1.0 * j / width  *  pi * T ); // [-degree,degree]
    temp = degree + temp;  // [0, 2*degree]
    for (int i = int(temp + 0.5); i < height + temp - 2 * degree; i++)
    {
        X = (int)((i - temp) *  (height) / (height - degree));
        if (X >= img.rows)
            X = img.rows - 1;
        if (X < 0)
            X = 0;

        for (int c = 0; c < chns; c++)
        {
            dst.at<Vec3b>(i, j)[c] = img.at<Vec3b>(X, j)[c];
        }
    }
}

测试1:

测试2:

4、参考文献

1、《学习OpenCV》,清华大学出版社,Gary Bradski, Adrian kaehler著

2、仿射变换

http://www.opencv.org.cn/opencvdoc/2.3.2/html/doc/tutorials/imgproc/imgtrans/warp_affine/warp_affine.html

3、PhotoShop算法实现高级篇--挤压特效(三十六)

https://blog.csdn.net/kezunhai/article/details/41873775

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-11-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 AI科技时讯 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • https://www.cnblogs.com/pingwen/p/12503047.html
  • 一、图像挤压特效
    • 1、原理
      • 2、实现
        • 3、测试效果
        • 二、哈哈镜特效
          • 1、原理
            • 2、实现
              • 3、测试效果
              • 三、图像扭曲
              • 4、参考文献
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档