图像处理哈哈镜

2019-04-26 17:31:27 IKMIC 阅读数 432

在网上找了很多,没有找到比较合适的,所以决定自己在前人的基础上进行一些改善。

   
      protected  static Bitmap change2bitmap(Bitmap mbitmap) {
          int width = mbitmap.getWidth();
          int height = mbitmap.getHeight();
          int pixR = 0;
          int pixG = 0;
          int pixB = 0;
          int newR = 0;
          int newG = 0;
          int radius=700;//半径
          double dis =0.0;
          int newB = 0;
          int buf[] =new int[width * height];
          int centerX = 500;
          int centerY =1100;//圆心坐标
          int pixels[]=new int[width * height];
         mbitmap.getPixels(buf, 0, width, 0, 0, width, height);
          for (int i = 0; i < width; i++)
          {
              for (int j = 0; j < height; j++)
              {
                  int arrl_color = buf[j * width + i];
                  pixR = red(arrl_color);
                  pixG = green(arrl_color);
                  pixB = blue(arrl_color);
                  newR = pixR;
                  newG = pixG;
                  newB = pixB;
                   int   distance =  ((centerX - i) * (centerX - i) + (centerY - j) * (centerY - j));
                  dis=Math.sqrt(distance);
                  if (distance <= radius * radius)
                  {

                      int src_x1 = i - centerX;
                      int src_y1 = j - centerY;
                      int  src_x = (int)((dis/radius /2+0.5)*src_x1);
                      int  src_y = (int)((dis/radius /2+0.5)*src_y1);
                      src_x = src_x+ centerX;
                      src_y = src_y + centerY;
                      int src_color = buf[src_y * width + src_x];
                      newR = red(src_color);
                      newG = green(src_color);
                      newB = blue(src_color);

                  }

                  newR = Math.min(255, Math.max(0, newR));
                  newG = Math.min(255, Math.max(0, newG));
                  newB = Math.min(255, Math.max(0, newB));
                  pixels[width * j + i] = Color.argb(255, newR, newG, newB);
              }
          }



          mbitmap = Bitmap.createBitmap(pixels, width, height, Bitmap.Config.ARGB_4444);
          return mbitmap;


      }

  }

重点代码如下:
int src_x1 = (int) ((float) (i - centerX) );
int src_y1 = (int) ((float) (j - centerY)
int src_x = (int)((dis/radius /2+0.5)*src_x1);
int src_y = (int)((dis/radius /2+0.5)*src_y1);
src_x = src_x+ centerX;
src_y = src_y + centerY;
算法主要用到的还是一元二次方程,
相比较之前算法扩散范围变小,
扩散幅度由一元二次方程A值进行调控。
未调整前:
在这里插入图片描述
调整后:
在这里插入图片描述

2016-05-06 20:06:20 u012590570 阅读数 2885

图像处理的哈哈镜

说起哈哈镜这个东西,好像已经很长时间没有见过了,这曾经在小时候是带来很多乐趣的东西。哈哈镜嘛,无非就是凹面镜或者凸面镜,什么效果呢?凹面镜把人变瘦了,凸面镜把人变胖了。

反映在图像上呢,就是图像的局部的缩放。注意不是整体的放大或缩小,只是一个区域被放大和缩小。为了简单期间,只讨论圆形的区域,因此无非存在两种情况,圆形区域的中心被放大周匝被缩小,或者中心被缩小周匝被放大,而且由中心到周匝的这个缩小放大时逐渐连续变化的(不是突然从缩小变成了放大)。

因此,我们构造了这样一条曲线(以中心缩小,周匝放大为例):
这里写图片描述
这张图上,横坐标是目标图像上的点到圆心的距离,纵坐标是原始图像上的点到圆心的距离,如果是蓝线就是不变换喽,如果是红线呢,会发现比如目标图像上距离圆心30左右的点在原始波形上是距离圆心50左右的点,这个意思很明显了,就是中心区域被缩小了。

至于怎么构造这样一条曲线,这是数学的事,恐怕有很多种办法可以构造。这里说两个必须满足的条件:①红线和蓝线的起点和终点必须是相同的,这个意思是说形变只发生在一个圆形区域内,圆形区域外图像不形变。②曲线的导数必须是连续的,试想一下,如果导数不连续,那么反映在图像上那就是缩小到放大的变化过程不连续了,这里尤其要多说一句,曲线的导数连续,要求在曲线的末端(我这图上是100的位置)导数必须为1。

把这个图上的两个曲线做个除法,就是下面这个结果:
这里写图片描述
这个图实际上说明了一件事,圆心位置的缩放比例是0.5,我们正是根据这个值去构造上面讲的曲线的。

然后剩下的事情就好办了,扫描图像上的点,看看像素是否在圆形区域内(到圆心的距离是不是大于圆的半径),如果不在圆内就原封不动从原始图像上复制过来,如果在圆内,就根据上面的方法找它在原始图像上对应的位置,做插值。

看一下效果,先是原始图像:
这里写图片描述

下面是处理后的图像,所选区域是以狗鼻子为中心的半径为100的圆。下图中中心点的缩放比例依次为:0.5、0.7、0.8、1.2、1.5、2.0
这里写图片描述

是不是很好玩?

我估计小女生们喜欢用美颜相机的瘦脸放大眼睛的功能估计是与此类似的算法。

2015-04-22 12:36:35 Trent1985 阅读数 1591


[函数名称]

  哈哈镜效果函数  WriteableBitmap DistortingMirrorProcess(WriteableBitmap src, int x, int y)

[算法说明]

  哈哈镜效果图像实际上是一种图像形变特效而已,对于这个特效,我们可以通过三角变换来实现。

  1,对于哈哈镜效果变换,首先它有两个参数,原点坐标和特效影响因子。

  对于图像中的像素点P(x,y),假设原点坐标为XY,那么,根据三角函数变换可以得到:

  当前像素P的相对坐标cX,cY:



        /// <summary>
        /// Distorting mirror process.
        /// </summary>
        /// <param name="src">The source image.</param>
        /// <param name="x">Origin of coordinates in x direction.</param>
        /// <param name="y">Origin of coordinates in y direction.</param>
        /// <returns></returns>
         public static WriteableBitmap DistortingMirrorProcess(WriteableBitmap src, int x, int y)////哈哈镜特效
         {
             if (src != null)
             {
                 int w = src.PixelWidth;
                 int h = src.PixelHeight;
                 WriteableBitmap srcImage = new WriteableBitmap(w, h);
                 byte[] temp = src.PixelBuffer.ToArray();
                 byte[] tempMask = (byte[])temp.Clone();
                 int radius = 0;
                 double theta = 0;
                 int tX = 0;
                 int tY = 0;
                 int mapX = 0;
                 int mapY = 0;
                 int mapR=0;
                 for (int j = 0; j < h; j++)
                 {
                     for (int i = 0; i < w; i++)
                     {
                         tX = i - x;
                         tY = j - y;
                         theta = Math.Atan2((double)tY, (double)tX);
                         radius = (int)Math.Sqrt((double)(tX * tX + tY * tY));
                         mapR = (int)(Math.Sqrt((double)radius * 100));
                         mapX = x + (int)(mapR * Math.Cos(theta));
                         mapY = y + (int)(mapR * Math.Sin(theta));
                         temp[i * 4 + j * w * 4] = tempMask[mapX * 4 + mapY * w * 4];
                         temp[i * 4 + 1 + j * w * 4] = tempMask[mapX * 4 + 1 + mapY * w * 4];
                         temp[i * 4 + 2 + j * w * 4] = tempMask[mapX * 4 + 2 + mapY * w * 4];
                     }
                 }
                 Stream sTemp = srcImage.PixelBuffer.AsStream();
                 sTemp.Seek(0, SeekOrigin.Begin);
                 sTemp.Write(temp, 0, w * 4 * h);
                 return srcImage;
             }
             else
             {
                 return null;
             }
         }

[图像效果]




2014-08-27 11:43:00 weixin_34129145 阅读数 340

最近迷上了各种App小应用开发,刚刚搞定了一个哈哈镜应用,先给大家上图看看处理效果:

                                                                       处理效果对比图1

处理效果对比图二

2014-01-03 09:24:28 cbacq 阅读数 2190

原文地址:http://www.cnblogs.com/magiccaptain/archive/2013/05/21/3091035.html

 

两个效果:放大和挤压,分别由MaxFrame和MinFrame函数实现, 可直接使用在摄像头中:

 

void MaxFrame(IplImage* frame)
{
    uchar* old_data = (uchar*)frame->imageData;
    uchar* new_data = new uchar[frame->widthStep * frame->height];
    
    int center_X = frame->width / 2;
    int center_Y = frame->height / 2;
    int radius = 400;
    int newX = 0;
    int newY = 0;

    int real_radius = (int)(radius / 2.0);
    for (int i = 0; i < frame->width; i++)
    {
        for (int j = 0; j < frame->height; j++)
        {
            int tX = i - center_X;
            int tY = j - center_Y;

            int distance = (int)(tX * tX + tY * tY);
            if (distance < radius * radius)
            {
                newX = (int)((float)(tX) / 2.0);
                newY = (int)((float)(tY) / 2.0);

                newX = (int) (newX * (sqrt((double)distance) / real_radius));
                newX = (int) (newX * (sqrt((double)distance) / real_radius));

                newX = newX + center_X;
                newY = newY + center_Y;

                new_data[frame->widthStep * j + i * 3] = old_data[frame->widthStep * newY + newX * 3];
                new_data[frame->widthStep * j + i * 3 + 1] =old_data[frame->widthStep * newY + newX * 3 + 1];
                new_data[frame->widthStep * j + i * 3 + 2] =old_data[frame->widthStep * newY + newX * 3 + 2];
            }
            else
            {
                new_data[frame->widthStep * j + i * 3] =  old_data[frame->widthStep * j + i * 3];
                new_data[frame->widthStep * j + i * 3 + 1] =  old_data[frame->widthStep * j + i * 3 + 1];
                new_data[frame->widthStep * j + i * 3 + 2] =  old_data[frame->widthStep * j + i * 3 + 2];
            }
        }
    }
    memcpy(old_data, new_data, sizeof(uchar) * frame->widthStep * frame->height);
    delete new_data;
}


 

void MinFrame(IplImage* frame)
{
    uchar* old_data = (uchar*)frame->imageData;
    uchar* new_data = new uchar[frame->widthStep * frame->height];

    int center_X = frame->width / 2;
    int center_Y = frame->height / 2;

    int radius = 0;
    double theta = 0;
    int newX = 0;
    int newY = 0;

    for (int i = 0; i < frame->width; i++)
    {
        for (int j = 0; j < frame->height; j++)
        {
            int tX = i - center_X;
            int tY = j - center_Y;

            theta = atan2((double)tY, (double)tX);
            radius = (int)sqrt((double)(tX * tX) + (double) (tY * tY));
            int newR = (int)(sqrt((double)radius) * 12);
            newX = center_X + (int)(newR * cos(theta));
            newY = center_Y + (int)(newR * sin(theta));

            if (!(newX > 0 && newX < frame->width))
            {
                newX = 0;
            }
            if (!(newY > 0 && newY < frame->height))
            {
                newY = 0;
            }

            new_data[frame->widthStep * j + i * 3] = old_data[frame->widthStep * newY + newX * 3];
            new_data[frame->widthStep * j + i * 3 + 1] =old_data[frame->widthStep * newY + newX * 3 + 1];
            new_data[frame->widthStep * j + i * 3 + 2] =old_data[frame->widthStep * newY + newX * 3 + 2];
        }
    }
    memcpy(old_data, new_data, sizeof(uchar) * frame->widthStep * frame->height);
    delete new_data;
}