opencv 交叉冲印,怀旧风格,光照效果,漏光滤镜的c++实现

交叉冲印滤镜又叫做正片负冲滤镜,关于它的原理我一直没找到,希望有大佬给我甩个链接。

我用的测试图像在这里

我实现的交叉冲印是使用上图这样的点运算来实现的,下面是我的代码

void punchFilter(Mat src) {
    int width = src.rows;
    int height = src.cols;
    int gray, value;
    int rMap[256], gMap[256], bMap[256];
    for (int i = 0; i < 256; i++){
        value = i < 128 ? i : 256 - i;
        gray = (int)pow(value, 3) / 16384; // value的3次方再除以16384
        rMap[i] = i < 128 ? gray : 256 - gray;
        gray = (int)pow(value, 2) / 128; // value的2次方再除以128
        gMap[i] = i < 128 ? gray : 256 - gray;
        bMap[i] = i / 2 + 0x25;//0x25 = 37
    }

    for (int j = 0; j < width - 1; j++) {
        uchar* data = src.ptr<uchar>(j);
        for (int i = 0; i < height - 1; i++) {
            int b = bMap[data[i * 3]];
            int g = gMap[data[i * 3 + 1]];
            int r = rMap[data[i * 3 + 2]];
            data[i * 3] = min(255, max(0, b));
            data[i * 3 + 1] = min(255, max(0, g));
            data[i * 3 + 2] = min(255, max(0, r));
        }
    }
    imshow("交叉冲印滤镜", src);
}

交叉冲印算法实现

效果图是这样的

这是怀旧风格滤镜,对原像素点的R、G、B进行变换

void recall(Mat src) {
    int width = src.rows;
    int height = src.cols;

    Mat img(src.size(), CV_8UC3);

    int x, y;
    for (y = 0; y < height;y++) {
        uchar* P0 = src.ptr<uchar>(y);
        uchar* P1 = img.ptr<uchar>(y);
        for (x = 0; x < width; x++) {
            float R = P0[3 * x + 2];
            float G = P0[3 * x + 1];
            float B = P0[3 * x];
            float newR = 0.393 * R + 0.769 * G + 0.189 * B;
            float newG = 0.349 * R + 0.686 * G + 0.168 * B;
            float newB = 0.272 * R + 0.534 * G + 0.131 * B;
            if (newR < 0) newR = 0;
            if (newR > 255) newR = 255;
            if (newG < 0) newG = 0;
            if (newG > 255) newG = 255;
            if (newB < 0) newB = 0;
            if (newB > 255) newB = 255;
            P1[3 * x] = (uchar)newB;
            P1[3 * x + 1] = (uchar)newG;
            P1[3 * x + 2] = (uchar)newR;
        }
    }
    imshow("怀旧滤镜实现", img);
}

效果图:

好像有点问题啊,图片不发黄啊

实现代码:

void light(int X, int Y, int K, int R, Mat src) {
    int width = src.rows;
    int height = src.cols;
    double distance;
    int x, y;
    Mat img;
    vector<Mat> m(3);
    split(src, m);
    for (y = 0; y < width ; y++) {
        for (x = 0; x < height; x++) {
            distance = sqrt((X - x) * (X - x) + (Y - y) * (Y - y));
            if (distance < R) {
                int temp = K * (0 > 1 - distance / R ? 0 : 1 - distance / R);
                if (temp > 255) temp = 255;
                int a = m[0].at<uchar>(x, y) + temp;
                m[0].at<uchar>(x, y) = MIN(255, MAX(0, a));
                a = m[1].at<uchar>(x, y) + temp;
                m[1].at<uchar>(x, y) = MIN(255, MAX(0, a));
                a = m[2].at<uchar>(x, y) + temp;
                m[2].at<uchar>(x, y) = MIN(255, MAX(0, a));
            }
        }
    }
    merge(m, img);
    imshow("光照滤镜实现", img);
}

效果图:

代码如下:

void leak(Mat src1, Mat src)
{
    int width = src1.cols, height = src1.rows;
    float newB;
    float newG;
    float newR;
    Mat img(src1.size(), CV_8UC3);
    for (int y = 0; y < height; y++)
    {
        uchar* P0 = src.ptr<uchar>(y);
        uchar* P1 = src1.ptr<uchar>(y);
        uchar* P3 = img.ptr<uchar>(y);
        for (int x = 0; x < width; x++)
        {

            if (P1[3 * x] <= 128)
            {
                newB = P0[3 * x] * P1[3 * x] / 128;
            }
            else
                newB = 255 - ((255 - P0[3 * x]) * (255 - P1[3 * x])) / 128;
            if (newB > 255)
            {
                newB = 255;
            }
            if (P1[3 * x + 1] <= 128)
            {
                newG = P0[3 * x + 1] * P1[3 * x + 1] / 128;
            }
            else
                newG = 255 - ((255 - P0[3 * x + 1]) * (255 - P1[3 * x + 1])) / 128;
            if (newG > 255)
            {
                newG = 255;
            }
            if (P1[3 * x + 2] <= 128)
            {
                newR = P0[3 * x + 2] * P1[3 * x + 2] / 128;
            }
            else
                newR = 255 - ((255 - P0[3 * x + 2]) * (255 - P1[3 * x + 2])) / 128;
            if (newR > 255)
            {
                newR = 255;
            }
            P3[3 * x] = newB;
            P3[3 * x + 1] = newG;
            P3[3 * x + 2] = newR;

        }imshow("漏光滤镜", img);
    }
}

漏光模板,用PS随便拉个前景色就好了

其实自己写的部分也没有多少,大部分还是在网上拼拼凑凑,终于得到了我想要的结果而已.

经过课设发现自己对于数字图像这块还是学习还是不够的,趁着寒假努力点吧.

最后附上整个项目的代码:

#include <opencv2/opencv.hpp>
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <stdio.h>
#include <iostream>

using namespace cv;
using namespace std;
//交叉冲印
void punchFilter(Mat src);
//怀旧风格滤镜
void recall(Mat src);
//光照效果滤镜
void light(int X, int Y, int K, int R, Mat src);//XY是光源坐标,K光照系数,R光照半径
//漏光滤镜
void leak(Mat src, Mat msak);

int main(int argc, char** argv) {
    while (1) {
        cout << "请选择显示的滤镜效果" << endl;
        cout << "1、交叉冲印滤镜" << endl;
        cout << "2、怀旧风格滤镜" << endl;
        cout << "3、光照效果滤镜" << endl;
        cout << "4、漏光滤镜" << endl;
        int choice;
        cin >> choice;
        switch (choice) {
        case 1: {
            Mat src = imread(argv[1]);
            Mat p_temp(src.rows, src.cols, CV_8UC3, src.data);
            imshow("原图", src);
            punchFilter(p_temp);
            break;
        }
        case 2: {
            Mat src = imread(argv[1]);
            Mat r_temp(src.rows, src.cols, CV_8UC3, src.data);
            imshow("原图", src);
            recall(r_temp);
            break;
        }
        case 3: {
            Mat src = imread(argv[1]);
            Mat l_temp(src.rows, src.cols, CV_8UC3, src.data);
            int X, Y, K, R;
            cout << "请输入光源坐标(x,y),光照系数,光照半径" << endl;
            cin >> X >> Y >> K >> R;
            imshow("原图", src);
            light(X, Y, K, R, l_temp);
            break;
        }
        case 4: {
            Mat src = imread(argv[1]);
            Mat leak_temp(src.rows, src.cols, CV_8UC3, src.data);
            Mat mask = imread("C:\\Users\\18704\\Desktop\\mask.png");
            imshow("原图", src);
            leak(leak_temp, mask);
        }
        default:{
            cout << "无效字符,请重新输入" << endl;
            break;
        }
    }
    waitKey(0);
    }
    return 0;
}

void punchFilter(Mat src) {
    int width = src.rows;
    int height = src.cols;
    int gray, value;
    int rMap[256], gMap[256], bMap[256];
    for (int i = 0; i < 256; i++){
        value = i < 128 ? i : 256 - i;
        gray = (int)pow(value, 3) / 16384; // value的3次方再除以16384
        rMap[i] = i < 128 ? gray : 256 - gray;
        gray = (int)pow(value, 2) / 128; // value的2次方再除以128
        gMap[i] = i < 128 ? gray : 256 - gray;
        bMap[i] = i / 2 + 0x25;//0x25 = 37
    }

    for (int j = 0; j < width - 1; j++) {
        uchar* data = src.ptr<uchar>(j);
        for (int i = 0; i < height - 1; i++) {
            int b = bMap[data[i * 3]];
            int g = gMap[data[i * 3 + 1]];
            int r = rMap[data[i * 3 + 2]];
            data[i * 3] = min(255, max(0, b));
            data[i * 3 + 1] = min(255, max(0, g));
            data[i * 3 + 2] = min(255, max(0, r));
        }
    }
    imshow("交叉冲印滤镜", src);
}

void recall(Mat src) {
    int width = src.rows;
    int height = src.cols;

    Mat img(src.size(), CV_8UC3);

    int x, y;
    for (y = 0; y < height;y++) {
        uchar* P0 = src.ptr<uchar>(y);
        uchar* P1 = img.ptr<uchar>(y);
        for (x = 0; x < width; x++) {
            float R = P0[3 * x + 2];
            float G = P0[3 * x + 1];
            float B = P0[3 * x];
            float newR = 0.393 * R + 0.769 * G + 0.189 * B;
            float newG = 0.349 * R + 0.686 * G + 0.168 * B;
            float newB = 0.272 * R + 0.534 * G + 0.131 * B;
            if (newR < 0) newR = 0;
            if (newR > 255) newR = 255;
            if (newG < 0) newG = 0;
            if (newG > 255) newG = 255;
            if (newB < 0) newB = 0;
            if (newB > 255) newB = 255;
            P1[3 * x] = (uchar)newB;
            P1[3 * x + 1] = (uchar)newG;
            P1[3 * x + 2] = (uchar)newR;
        }
    }
    imshow("怀旧滤镜实现", img);
}

void light(int X, int Y, int K, int R, Mat src) {
    int width = src.rows;
    int height = src.cols;
    double distance;
    int x, y;
    Mat img;
    vector<Mat> m(3);
    split(src, m);
    for (y = 0; y < width ; y++) {
        for (x = 0; x < height; x++) {
            distance = sqrt((X - x) * (X - x) + (Y - y) * (Y - y));
            if (distance < R) {
                int temp = K * (0 > 1 - distance / R ? 0 : 1 - distance / R);
                if (temp > 255) temp = 255;
                int a = m[0].at<uchar>(x, y) + temp;
                m[0].at<uchar>(x, y) = MIN(255, MAX(0, a));
                a = m[1].at<uchar>(x, y) + temp;
                m[1].at<uchar>(x, y) = MIN(255, MAX(0, a));
                a = m[2].at<uchar>(x, y) + temp;
                m[2].at<uchar>(x, y) = MIN(255, MAX(0, a));
            }
        }
    }
    merge(m, img);
    imshow("光照滤镜实现", img);
}

void leak(Mat src1, Mat src)
{
    int width = src1.cols, height = src1.rows;
    float newB;
    float newG;
    float newR;
    Mat img(src1.size(), CV_8UC3);
    for (int y = 0; y < height; y++)
    {
        uchar* P0 = src.ptr<uchar>(y);
        uchar* P1 = src1.ptr<uchar>(y);
        uchar* P3 = img.ptr<uchar>(y);
        for (int x = 0; x < width; x++)
        {

            if (P1[3 * x] <= 128)
            {
                newB = P0[3 * x] * P1[3 * x] / 128;
            }
            else
                newB = 255 - ((255 - P0[3 * x]) * (255 - P1[3 * x])) / 128;
            if (newB > 255)
            {
                newB = 255;
            }
            if (P1[3 * x + 1] <= 128)
            {
                newG = P0[3 * x + 1] * P1[3 * x + 1] / 128;
            }
            else
                newG = 255 - ((255 - P0[3 * x + 1]) * (255 - P1[3 * x + 1])) / 128;
            if (newG > 255)
            {
                newG = 255;
            }
            if (P1[3 * x + 2] <= 128)
            {
                newR = P0[3 * x + 2] * P1[3 * x + 2] / 128;
            }
            else
                newR = 255 - ((255 - P0[3 * x + 2]) * (255 - P1[3 * x + 2])) / 128;
            if (newR > 255)
            {
                newR = 255;
            }
            P3[3 * x] = newB;
            P3[3 * x + 1] = newG;
            P3[3 * x + 2] = newR;

        }imshow("漏光滤镜", img);
    }
}

原文地址:https://www.cnblogs.com/lumping-boy/p/12164045.html

时间: 2024-10-17 07:32:16

opencv 交叉冲印,怀旧风格,光照效果,漏光滤镜的c++实现的相关文章

怀旧风格照片特效

我想说怀旧风格的效果很容易实现,就那么几句话,也没啥可说的. 1 % 怀旧风格滤镜 2 clear all; 3 close all; 4 [FileName,PathName] = uigetfile('*.jpg','Open an Image File'); 5 img = imread([PathName FileName]); 6 figure, imshow(img); 7 img = double(img); 8 Rimg = img(:,:,1); 9 Gimg = img(:,

Python综合应用:教你用字符打印一张怀旧风格的照片

1. 前言第一次在学校机房里见到计算机,还是上古时期.计算机型号大概是LASER-310吧,有点记不清了.那会儿,显示器还是单色的,只能显示文本,每行最多显示80个字符.想看图片,印象中只能用针式打印机打印在两侧穿孔的宽行打印纸上,每个像素用一个字符表示,不同的字符代表不同的灰度,就像下图这个样子.有没有感觉到浓郁古风呢?其实,随便一张照片,十几行Python代码,你也可以打印出这样的效果,还可以保存成文件.下面,我就一步一步地演示一下. 2. 打开图片,转为灰度模式 Python用于图像处理的

Python综合应用:手把手教你用字符打印一张怀旧风格的照片

前言 第一次在学校机房里见到计算机,还是上古时期.计算机型号大概是LASER-310吧,有点记不清了.那会儿,显示器还是单色的,只能显示文本,每行最多显示80个字符.想看图片,印象中只能用针式打印机打印在两侧穿孔的宽行打印纸上,每个像素用一个字符表示,不同的字符代表不同的灰度,就像下图这个样子.有没有感觉到浓郁古风呢?其实,随便一张照片,十几行Python代码,你也可以打印出这样的效果,还可以保存成文件.下面,我就一步一步地演示一下. 打开图片,转为灰度模式 Python用于图像处理的模块有很多

CSSgram-使用CSS Filters和CSS Blend Modes实现Instagram风格滤镜

1. 简介 CSSgram是一个简单易用的CSS库,组合CSS Filter和CSS Blend Modes实现的Instagram风格的图片滤镜,通过在图片上叠加颜色或渐变模拟实现滤镜,可以节省大量的图片处理时间,增加线上"玩弄"图片的乐趣. 2. 兼容性 本库主要基于 CSS Filters and CSS Blend Modes,浏览器兼容性也主要依赖于这两个特性. Google Chrome: 43+ Mozilla Firefox: 38+ Opera: 32+ Safari

iOS滤镜 图片处理

摘要:本文结合实例详解了OS X和iOS图像处理框架Core Image的使用,如何通过Core Image来创建和使用iOS的内置滤镜,非常适合初学者学习.虽然示例代码是用Swift写的iOS程序,不过实现概念很容易转换到Objective-C和OS X. 这篇文章会为初学者介绍一下Core Image,一个OS X和iOS的图像处理框架. 如果你想跟着本文中的代码学习,你可以在GitHub上下载示例工程.示例工程是一个iOS应用程序,列出了系统提供的大量图像滤镜以供选择,并提供了一个用户界面

[Android] 图像各种处理系列文章合集

    这是我最近在做Android随手拍一个项目的各种网上关于图片处理的资料,以前学过数字图像处理都是用C++写的,下面的资料个人认为是非常优秀的各种集合,另一方面它是在线笔记,希望对大家有所帮助吧!其中我截图部分都是作者经典的文章显示效果. 1.<android图片处理总结>作者邮箱可能是[email protected],同时sjf0115转载很多文章,非常优秀的一本短书.感谢作者和博主sjf0115(落日小屋). android图像处理系列之三--图片色调饱和度.色相.亮度处理    

详解OS X和iOS图像处理框架Core Image

转自:http://www.csdn.net/article/2015-02-13/2823961-core-image 摘要:本 文结合实例详解了OS X和iOS图像处理框架Core Image的使用,如何通过Core Image来创建和使用iOS的内置滤镜,非常适合初学者学习.虽然示例代码是用Swift写的iOS程序,不过实现概念很容易转换到 Objective-C和OS X. 这篇文章会为初学者介绍一下Core Image,一个OS X和iOS的图像处理框架. 如果你想跟着本文中的代码学习

35款512像素的高清晰PNG图标

PNG图标是网页中经常使用的一种图标素材,这里收集了35款512像素的PNG图标可供大家免费下载. 1.各种高清电脑显示器PNG图标 下载地址>> 2.超酷电脑桌面图标PNG图标 下载地址>> 3.超清精美桌面图标PNG图标 下载地址>> 4.经典苹果电脑桌面图标PNG图标 下载地址>> 5.经典电脑桌面图标PNG图标 下载地址>> 6.四种颜色的橙子PNG图标 下载地址>> 7.超可爱动物毛绒公仔PNG图标 下载地址>>

大数据之三:几个名词

Hadoop=HDFS+Hive+Pig+... HDFS: 存储系统MapReduce:计算系统Hive:提供给SQL开发人员(通过HiveQL)的MapReduce,基于Hadoop的数据仓库框架Pig:基于Hadoop的语言开发的HBase:NoSQL数据库Flume:一个收集处理Hadoop数据的框架Oozie:一个让用户以多种语言(如MapReduce,Pig和Hive)定义一系列作业的工作流处理系统Ambari:一个基于web的部署/管理/监控Hadoop集群的工具集Avro:允许编