OpenCV-Python实现怀旧滤镜与连环画滤镜

编辑: admin 分类: python 发布时间: 2021-12-24 来源:互联网
目录
  • 怀旧滤镜实现原理
    • 实现怀旧滤镜
  • 连环画滤镜原理
    • 实现连环画滤镜
  • 熔铸算法
    • 冰冻算法

      怀旧滤镜实现原理

      不管是荣耀华为手机还是其他的手机,我们都可以找到相机中的怀旧效果,这是手机中常用的一种滤镜效果。

      怀旧风格的设计主要是在图像的颜色空间进行处理。以BGR为例,对B、G、R这3个通道的颜色数值进行处理,让图像有一种泛黄的怀旧效果。设计的转换公式如下:

      B=0.272r+0.534g+0.131*b

      G=0.349r+0.686g+0.168*b

      R=0.393r+0.769g+0.189*b

      计算公式中的小写的bgr是原图像的RGB通道的颜色,结果BGR是怀旧变换后的值。需要注意的是,颜色值的范围在[0,255],需要在程序中约束一下。

      实现怀旧滤镜

      既然我们已经了解了其实现的原理公式。下面我们直接上代码实现该功能,具体代码如下所示:

      def cowboy_effect(img):
          new_img = img.copy()
          h, w, n = img.shape
          for i in range(w):
              for j in range(h):
                  b = img[j, i, 0]
                  g = img[j, i, 1]
                  r = img[j, i, 2]
                  B = int(0.272 * r + 0.534 * g + 0.131 * b)
                  G = int(0.349 * r + 0.686 * g + 0.168 * b)
                  R = int(0.393 * r + 0.769 * g + 0.189 * b)
                  new_img[j, i, 0] = max(0, min(B, 255))
                  new_img[j, i, 1] = max(0, min(G, 255))
                  new_img[j, i, 2] = max(0, min(R, 255))
          return new_img
      
      
      if __name__ == "__main__":
          img = cv2.imread("48.jpg")
          cv2.imshow("0", img)
          cv2.imshow("1", cowboy_effect(img))
          cv2.waitKey()
          cv2.destroyAllWindows()
      

      运行之后,效果如下:

      效果

      连环画滤镜原理

      从怀旧滤镜就可以看出来,其实相机的各种滤镜效果就是对RGB的颜色通道进行计算处理。既然怀旧滤镜有公式,那么肯定的连环画滤镜也有公式。它的具体公式如下:

      R = |g – b + g + r| * r / 256

      G = |b – g + b + r| * r / 256

      B = |b – g + b + r| * g / 256

      实现连环画滤镜

      有了公式,下面直接套用公式即可。具体代码如下所示:

      # 连环画滤镜
      def comics_effect(img):
          new_img = img.copy()
          h, w, n = img.shape
          for i in range(w):
              for j in range(h):
                  b = img[j, i, 0]
                  g = img[j, i, 1]
                  r = img[j, i, 2]
                  R = int(int(abs(g - b + g + r)) * r / 256)
                  G = int(int(abs(b - g + b + r)) * r / 256)
                  B = int(int(abs(b - g + b + r)) * g / 256)
                  new_img[j, i, 0] = R
                  new_img[j, i, 1] = G
                  new_img[j, i, 2] = B
          return new_img
      
      
      if __name__ == "__main__":
          img = cv2.imread("48.jpg")
          cv2.imshow("0", img)
          cv2.imshow("1", comics_effect(img))
          cv2.waitKey()
          cv2.destroyAllWindows()
      

      运行之后,效果如下:

      连环画滤镜

      综上所述,基本上所有的基础滤镜都是通过对RGB通道的颜色值进行公式计算得到的。当然,要是数学很好,又对算法情有独钟的读者,可以自己自研滤镜算法丰富滤镜的效果。

      熔铸算法

      r = r*128/(g+b +1);
      g = g*128/(r+b +1);
      b = b*128/(g+r +1);

      冰冻算法

      r = (r-g-b)*3/2;
      g = (g-r-b)*3/2;
      b = (b-g-r)*3/2;

      #include <math.h>
      #include <opencv/cv.h>
      #include <opencv/highgui.h>
      #define MAXSIZE (32768)
      using namespace cv;
      using namespace std;
       
      void casting(const Mat& src)
      {
       Mat img;
       src.copyTo(img);
       int width=src.cols;
       int heigh=src.rows;
       Mat dst(img.size(),CV_8UC3);
       for (int y=0;y<heigh;y++)
       {
        uchar* imgP=img.ptr<uchar>(y);
        uchar* dstP=dst.ptr<uchar>(y);
        for (int x=0;x<width;x++)
        {
         float b0=imgP[3*x];
         float g0=imgP[3*x+1];
         float r0=imgP[3*x+2];
       
         float b = b0*255/(g0+r0+1);
         float g = g0*255/(b0+r0+1);
         float r = r0*255/(g0+b0+1);
       
         r = (r>255 ? 255 : (r<0? 0 : r));
         g = (g>255 ? 255 : (g<0? 0 : g));
         b = (b>255 ? 255 : (b<0? 0 : b));
       
         dstP[3*x] = (uchar)b;
         dstP[3*x+1] = (uchar)g;
         dstP[3*x+2] = (uchar)r;
        }
       }
       imshow("熔铸",dst);
       imwrite("D:/img/熔铸.jpg",dst);
       
      }
       
      void freezing(const Mat& src)
      {
       Mat img;
       src.copyTo(img);
       int width=src.cols;
       int heigh=src.rows;
       Mat dst(img.size(),CV_8UC3);
       for (int y=0;y<heigh;y++)
       {
        uchar* imgP=img.ptr<uchar>(y);
        uchar* dstP=dst.ptr<uchar>(y);
        for (int x=0;x<width;x++)
        {
         float b0=imgP[3*x];
         float g0=imgP[3*x+1];
         float r0=imgP[3*x+2];
       
         float b = (b0-g0-r0)*3/2;
         float g = (g0-b0-r0)*3/2;
         float r = (r0-g0-b0)*3/2;
       
         r = (r>255 ? 255 : (r<0? -r : r));
         g = (g>255 ? 255 : (g<0? -g : g));
         b = (b>255 ? 255 : (b<0? -b : b));
      //    r = (r>255 ? 255 : (r<0? 0 : r));
      //    g = (g>255 ? 255 : (g<0? 0 : g));
      //    b = (b>255 ? 255 : (b<0? 0 : b));
         dstP[3*x] = (uchar)b;
         dstP[3*x+1] = (uchar)g;
         dstP[3*x+2] = (uchar)r;
        }
       }
       imwrite("D:/img/冰冻.jpg",dst);
      }
       
      int main()
      {
       Mat src = imread("D:/img/scene04.jpg",1);
       imshow("src",src);
       casting(src);
       freezing(src);
       
       waitKey();
       
      }
      
      

      到此这篇关于OpenCV-Python实现怀旧滤镜与连环画滤镜的文章就介绍到这了,更多相关OpenCV 怀旧滤镜与连环画滤镜内容请搜索hwidc以前的文章或继续浏览下面的相关文章希望大家以后多多支持hwidc!