基于opencv的相机之特效功能实现(八)

2024-06-13 19:58

本文主要是介绍基于opencv的相机之特效功能实现(八),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

简介

  本篇是对实现图片处理功能:【特效】实现的记录。

素描

实现原理

  首先将图像灰阶化,然后将图像反相,将反相后的图片进行高斯模糊,最后将模糊后的图片和原图片,以颜色减淡方式叠加,达到素描效果。
参考资料:http://blog.csdn.net/matrix_space/article/details/40589411

具体代码

JNIEXPORT void JNICALL Java_com_example_background_MyPicBackGround_croquisBackGround
(JNIEnv* env, jclass obj, jlong imageCroquis, jint value){Mat I_invert;  Mat I_gau;  float delta=0.01;  float alpha=0;  Mat I_dst;vector<Mat> channels;IplImage tmp1_1, tmp1_2, tmp1_3;IplImage tmp2_1, tmp2_2, tmp2_3;IplImage tmp3_1, tmp3_2, tmp3_3;Mat mat = Mat(*((Mat*)imageCroquis));split(mat, channels);tmp2_1 = channels.at(0);tmp2_2 = channels.at(1);tmp2_3 = channels.at(2);Mat Image_out(mat.size(), CV_32FC3);mat.convertTo(Image_out, CV_32FC3);Mat I(mat.size(), CV_32FC1);cv::cvtColor(Image_out, I, CV_BGR2GRAY);I=I/255.0;I_invert=-I+1.0;GaussianBlur(I_invert, I_gau, Size(25, 25), 0, 0);I_gau=-I_gau+1.0+delta;cv::divide(I, I_gau, I_dst);  I_dst = I_dst * 255.0;tmp1_1 = I_dst;Mat b(mat.size(), CV_32FC1);  Mat g(mat.size(), CV_32FC1);  Mat r(mat.size(), CV_32FC1);Mat rgb[]={b,g,r};  tmp3_1 = b;tmp3_2 = g;tmp3_3 = r;alpha = (float)value / 20.0;cvAddWeighted(&tmp1_1, alpha, &tmp2_1, (1-alpha), 0, &tmp3_1);cvAddWeighted(&tmp1_1, alpha, &tmp2_2, (1-alpha), 0, &tmp3_2);cvAddWeighted(&tmp1_1, alpha, &tmp2_3, (1-alpha), 0, &tmp3_3);cv::merge(rgb, 3, Image_out);Image_out.convertTo(mat, CV_8UC3);
}

  需要注意下,拖动条传入数据value会影响原图像和素面图像叠加的权重。

效果演示

  对应的效果图片如下:
            原图像                                             素描

老照片效果

实现原理

  根据转换公式:
参考文档:1、http://blog.csdn.net/yangtrees/article/details/91163372、http://blog.csdn.net/matrix_space/article/details/40432125

具体代码

JNIEXPORT void JNICALL Java_com_example_background_MyPicBackGround_oldBackGround
(JNIEnv* env, jclass obj, jlong imageOld, jint value){float alpha=0;  IplImage tmp1_1, tmp1_2, tmp1_3;IplImage tmp2_1, tmp2_2, tmp2_3;Mat Image_in = Mat(*((Mat*)imageOld));Mat Image_out(Image_in.size(), CV_32FC3);  Mat Image_2(Image_in.size(), CV_32FC3);  Image_in.convertTo(Image_2, CV_32FC3);  Mat r(Image_in.size(), CV_32FC1);  Mat g(Image_in.size(), CV_32FC1);  Mat b(Image_in.size(), CV_32FC1);  Mat out[]={b, g, r};  split(Image_2, out);  tmp1_1 = b;tmp1_2 = g;tmp1_3 = r;Mat r_new(Image_in.size(), CV_32FC1);  Mat g_new(Image_in.size(), CV_32FC1);  Mat b_new(Image_in.size(), CV_32FC1);  r_new=0.393*r+0.769*g+0.189*b;  g_new=0.349*r+0.686*g+0.168*b;  b_new=0.272*r+0.534*g+0.131*b;  Mat rgb[]={b_new, g_new, r_new};  tmp2_1 = b_new;tmp2_2 = g_new;tmp2_3 = r_new;alpha = (float)value / 20.0;cvAddWeighted(&tmp2_1, alpha, &tmp1_1, (1-alpha), 0, &tmp2_1);cvAddWeighted(&tmp2_1, alpha, &tmp1_2, (1-alpha), 0, &tmp2_2);cvAddWeighted(&tmp2_1, alpha, &tmp1_3, (1-alpha), 0, &tmp2_3);merge(rgb, 3, Image_out);Image_out.convertTo(Image_in, CV_8UC3);
}

效果演示

  对应的效果图片如下:
             原图像                                          老照片效果

浮雕效果

实现原理

  浮雕效果是对图像像素点进行卷积操作。
可以参考文档:1、http://blog.csdn.net/yangtrees/article/details/90906072、http://blog.csdn.net/matrix_space/article/details/40431061

具体代码

JNIEXPORT void JNICALL Java_com_example_background_MyPicBackGround_embossBackGround
(JNIEnv* env, jclass obj, jlong imageEmboss, jint value){Mat kernel;  Point anchor;  double delta;  int ddepth;  int kernel_size;  IplImage tmp1_1, tmp1_2, tmp1_3;float alpha = 0.5;ddepth=-1;  anchor=Point(-1,-1);  delta=0;  kernel_size=3;  Mat K_1;  float p;  p=3;  K_1=Mat::zeros(kernel_size, kernel_size, CV_32F);K_1.at<float>(0,2)=p;  K_1.at<float>(2,0)=-p;  Mat Image_in = Mat(*((Mat*)imageEmboss));tmp1_1 = Image_in;Mat Image_out(Image_in.size(), CV_32FC3);  Image_in.convertTo(Image_out, CV_32FC3);  tmp1_3 = Image_out;Mat Image_2(Image_in.size(), CV_32FC3);  Image_in.convertTo( Image_2, CV_32FC3);  Mat Image_x(Image_in.size(), CV_32FC3);  cv::filter2D(Image_2, Image_x, ddepth, K_1);  cv::add(Image_x, Scalar(128.0, 128.0, 128.0), Image_x);tmp1_2 = Image_x;alpha = (float)value / 20.0;cvAddWeighted(&tmp1_2, alpha, &tmp1_1, (1-alpha), 0, &tmp1_3);Image_out.convertTo(Image_in, CV_8UC3);
}

效果演示

  对应的效果图片如下:
            原图像                                        浮雕效果

卡通效果

实现原理

  首先将原图像灰阶、滤波之后,使用Laplacian进行边缘检测,接着对检测结果二值化处理。同时对原图像进行双边滤波处理。最后将二值化图像和双边滤波后图像叠加,形成卡通图像。参考资料:http://www.it165.net/pro/html/201503/36347.html

具体代码

JNIEXPORT void JNICALL Java_com_example_background_MyPicBackGround_cartoonBackGround(JNIEnv* env, jclass obj, jlong imageCartoon, jint value){IplImage tmp_1, tmp_2;float alpha = 0;Mat Image_in = Mat(*((Mat*)imageCartoon));tmp_1 = Image_in;Mat Image_out(Image_in.size(), CV_8UC3);Mat mask(Image_in.size(), CV_8UC1);  cv::Mat edge;cv::Mat grayImage;cv::cvtColor(Image_in, grayImage, CV_BGR2GRAY);cv::medianBlur(grayImage, grayImage, 7);cv::Laplacian(grayImage, edge, CV_8U, 5);cv::threshold(edge, mask, 80, 255, cv::THRESH_BINARY_INV);cv::Size size = Image_in.size();cv::Size reduceSize;reduceSize.width = size.width / 2;reduceSize.height = size.height / 2;cv::Mat reduceImage = cv::Mat(reduceSize, CV_8UC3);cv::resize(Image_in, reduceImage, reduceSize);cv::Mat tmp = cv::Mat(reduceSize, CV_8UC3);int repetitions = 7;for (int i=0 ; i < repetitions; i++){int kernelSize = 9;double sigmaColor = 9;double sigmaSpace = 7;cv::bilateralFilter(reduceImage, tmp, kernelSize, sigmaColor, sigmaSpace);cv::bilateralFilter(tmp, reduceImage, kernelSize, sigmaColor, sigmaSpace);}cv::Mat magnifyImage;cv::resize(reduceImage, magnifyImage, size);Image_out.setTo(0); magnifyImage.copyTo(Image_out, mask);tmp_2 = Image_out;alpha = (float)value / 20.0;cvAddWeighted(&tmp_2, alpha, &tmp_1, (1-alpha), 0, &tmp_2); Image_out.convertTo(Image_in, CV_8UC3);
}

效果演示

  对应的效果图片如下:
           原图像                                       卡通效果

渐变效果

实现原理

  以图像某个点为中心,设置它的亮度权重为1,离该中心越远的像素,亮度权重越低。最终形成中心到四周亮度渐变的效果。

具体代码

JNIEXPORT void JNICALL Java_com_example_background_MyPicBackGround_rampBackGround(JNIEnv* env, jclass obj, jlong imageRamp, jint value, jint newTouch_x, jint newTouch_y, jint screenHeight, jint screenWidth){int width,height;int i, j;float sum = 0, sum_tmp[2];float alpha = 0;Mat Image_in = Mat(*((Mat*)imageRamp));width = Image_in.rows;height = Image_in.cols;CvScalar s1;Mat Image_out(Image_in.size(), CV_32FC3);  Image_in.convertTo(Image_out, CV_32FC3);  Mat Image_2(Image_in.size(), CV_32FC3);  Image_in.convertTo(Image_2, CV_32FC3);  Mat Map(Image_in.size(), CV_32FC3);  Mat temp;  float val;  IplImage tmp_1, tmp_2;int touch_y = height * newTouch_x / screenHeight;int touch_x = width * newTouch_y / screenWidth;if((width - touch_x) > touch_x){sum_tmp[0] = (width - touch_x) * (width - touch_x);}else{sum_tmp[0] = touch_x * touch_x;}if((height - touch_y) > touch_y){sum_tmp[1] = (height - touch_y) * (height - touch_y);}else{sum_tmp[1] = touch_y * touch_y;}sum = std::sqrt(sum_tmp[0] + sum_tmp[1]);tmp_1 = Map;for(i = 0; i < height; i++){for(j= 0; j< width; j++){sum_tmp[0] = std::abs(i - touch_y) * std::abs(i - touch_y);sum_tmp[1] = std::abs(j - touch_x) * std::abs(j - touch_x);val =1 - (std::sqrt(sum_tmp[0] + sum_tmp[1]) / sum);val = val * val * val * val;s1.val[0] = val;s1.val[1] = val;s1.val[2] = val;s1.val[3] = val;cvSet2D(&tmp_1, j, i, s1);}}cv::multiply(Image_2, Map, Image_out);  tmp_1 = Image_out;tmp_2 = Image_in;alpha = (float)value / 20.0;cvAddWeighted(&tmp_1, alpha, &tmp_2, (1-alpha), 0, &tmp_1);Image_out.convertTo(Image_in, CV_8UC3);
}


   函数中,传入参数newTouch_x,newTouch_y为界面上图像点击点坐标,也就是渐变效果的中心位置。传入参数value为拖动条数据,也就是最后渐变效果的叠加权重。

  之前有说到以渐变中心点的亮度权重为1,向四周减小。这里将每个像素点对应亮度权重都保存在新建的图像Map中。接着将原图像和亮度权重通过
cv::multiply相乘,得到渐变结果保存在Image_out中。最后根据拖动条数据计算出来的叠加权重来或得原图像和渐变图像最后叠加输出效果。

效果演示

  对应的效果图片如下:
        原图像                                      渐变效果

模糊背景

实现原理

  根据传入的坐标为圆心,拖动条的数据为半径参数的圆为前景,其他为背景,将背景模糊掉。

具体代码

JNIEXPORT void JNICALL Java_com_example_background_MyPicBackGround_blurBackGround
(JNIEnv* env, jclass obj, jlong imageWhiteBlack, jint value, jint newTouch_x, jint newTouch_y, jint screenHeight, jint screenWidth){IplImage myEdofsrc, myEdofres, myEdofroi, myEdofTmp;int myEdofSize = 0, myEdofWidth, myEdofHeight;CvScalar myEdofs;Mat myEdofMat1, myEdofMat2, myEdofMat3, myEdofMat4;int i, j;myEdofMat1 = Mat(*((Mat*)imageWhiteBlack));myEdofsrc = myEdofMat1;myEdofWidth = myEdofMat1.rows;myEdofHeight = myEdofMat1.cols;int touch_y = myEdofHeight * newTouch_x / screenHeight;int touch_x = myEdofWidth * newTouch_y / screenWidth;myEdofSize = myEdofHeight * (value + 4)/ 40;myEdofMat2 = Mat(myEdofWidth, myEdofHeight, CV_8UC3, cv::Scalar(0, 0, 0));myEdofMat3 = Mat(myEdofWidth, myEdofHeight, CV_8UC3, cv::Scalar(0, 0, 0));myEdofMat4 = Mat(myEdofWidth, myEdofHeight, CV_8UC1);myEdofTmp = myEdofMat2;myEdofres = myEdofMat3;myEdofroi = myEdofMat4;cvZero(&myEdofroi);for(i=0;i<myEdofWidth;i++){for(j=0;j<myEdofHeight;j++){myEdofs = cvGet2D(&myEdofsrc, i, j);cvSet2D(&myEdofTmp, i, j, myEdofs);}}cvCircle(&myEdofroi, cvPoint(touch_y, touch_x), myEdofSize, CV_RGB(255, 255, 255), -1, 8, 0);cvAnd(&myEdofTmp, &myEdofTmp, &myEdofres, &myEdofroi);if(myEdofSize > 0){myEdofMat1.copyTo(myEdofMat2);myEdofTmp = myEdofMat2;myEdofsrc = myEdofMat1;cvSmooth(&myEdofsrc, &myEdofsrc, CV_GAUSSIAN, 33, 33);for(i=0;i<myEdofWidth;i++){for(j=0;j<myEdofHeight;j++){  myEdofs = cvGet2D(&myEdofres, i, j);  if((myEdofs.val[0] != 0) && (myEdofs.val[1] != 0) && (myEdofs.val[2] != 0)){  myEdofs = cvGet2D(&myEdofTmp, i, j);   cvSet2D(&myEdofsrc, i, j, myEdofs);  }  }  }}
}

效果演示

  对应的效果图片如下:
                            背景模糊图片

黑白背景效果

实现原理

  和模糊背景效果类似,只不过前置是将背景模糊掉,这是是将背景灰阶掉。

具体代码

JNIEXPORT void JNICALL Java_com_example_background_MyPicBackGround_whiteBlackBackGround
(JNIEnv* env, jclass obj, jlong imageWhiteBlack, jint value, jint newTouch_x, jint newTouch_y, jint screenHeight, jint screenWidth){int myGrayPartSize = 0, myGrayPartWidth, myGrayPartHeight;CvScalar myGrayParts;Mat myGrayPartMat1, myGrayPartMat2, myGrayPartMat3, myGrayPartMat4;IplImage myGrayPartsrc, myGrayPartres, myGrayPartroi, myGrayPartTmp;int i, j;float grayScale;myGrayPartMat1 = Mat(*((Mat*)imageWhiteBlack));myGrayPartsrc = myGrayPartMat1;myGrayPartWidth = myGrayPartMat1.rows;myGrayPartHeight = myGrayPartMat1.cols;int touch_y = myGrayPartHeight * newTouch_x / screenHeight;int touch_x = myGrayPartWidth * newTouch_y / screenWidth;myGrayPartSize = myGrayPartHeight * (value + 4)/ 40;;myGrayPartMat2 = Mat(myGrayPartWidth, myGrayPartHeight, CV_8UC3, cv::Scalar(0, 0, 0));myGrayPartMat3 = Mat(myGrayPartWidth, myGrayPartHeight, CV_8UC3, cv::Scalar(0, 0, 0));myGrayPartMat4 = Mat(myGrayPartWidth, myGrayPartHeight, CV_8UC1);myGrayPartTmp = myGrayPartMat2;myGrayPartres = myGrayPartMat3;myGrayPartroi = myGrayPartMat4;cvZero(&myGrayPartroi);for(i=0;i<myGrayPartWidth;i++){for(j=0;j<myGrayPartHeight;j++){myGrayParts = cvGet2D(&myGrayPartsrc, i, j);cvSet2D(&myGrayPartTmp, i, j, myGrayParts);}}cvCircle(&myGrayPartroi, cvPoint(touch_y, touch_x), myGrayPartSize, CV_RGB(255, 255, 255), -1, 8, 0);cvAnd(&myGrayPartTmp, &myGrayPartTmp, &myGrayPartres, &myGrayPartroi);if(myGrayPartSize > 0){      myGrayPartsrc = myGrayPartMat1;cvCvtColor(&myGrayPartsrc, &myGrayPartroi, CV_BGR2GRAY);for(i=0;i<myGrayPartWidth;i++){for(j=0;j<myGrayPartHeight;j++){  myGrayParts = cvGet2D(&myGrayPartres, i, j);  if((myGrayParts.val[0] == 0) || (myGrayParts.val[1] == 0) || (myGrayParts.val[2] == 0)){ myGrayParts = cvGet2D(&myGrayPartroi, i, j);myGrayParts.val[1] = myGrayParts.val[0];myGrayParts.val[2] = myGrayParts.val[0];cvSet2D(&myGrayPartsrc, i, j, myGrayParts);  }  }  }}       
}

效果演示

  对应的效果图片如下:
                         黑白背景图片
具体演示下载:http://download.csdn.net/detail/u011630458/9261617

这篇关于基于opencv的相机之特效功能实现(八)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1058274

相关文章

C++对象布局及多态实现探索之内存布局(整理的很多链接)

本文通过观察对象的内存布局,跟踪函数调用的汇编代码。分析了C++对象内存的布局情况,虚函数的执行方式,以及虚继承,等等 文章链接:http://dev.yesky.com/254/2191254.shtml      论C/C++函数间动态内存的传递 (2005-07-30)   当你涉及到C/C++的核心编程的时候,你会无止境地与内存管理打交道。 文章链接:http://dev.yesky

vcpkg安装opencv中的特殊问题记录(无法找到opencv_corexd.dll)

我是按照网上的vcpkg安装opencv方法进行的(比如这篇:从0开始在visual studio上安装opencv(超详细,针对小白)),但是中间出现了一些别人没有遇到的问题,虽然原因没有找到,但是本人给出一些暂时的解决办法: 问题1: 我在安装库命令行使用的是 .\vcpkg.exe install opencv 我的电脑是x64,vcpkg在这条命令后默认下载的也是opencv2:x6

通过SSH隧道实现通过远程服务器上外网

搭建隧道 autossh -M 0 -f -D 1080 -C -N user1@remotehost##验证隧道是否生效,查看1080端口是否启动netstat -tuln | grep 1080## 测试ssh 隧道是否生效curl -x socks5h://127.0.0.1:1080 -I http://www.github.com 将autossh 设置为服务,隧道开机启动

时序预测 | MATLAB实现LSTM时间序列未来多步预测-递归预测

时序预测 | MATLAB实现LSTM时间序列未来多步预测-递归预测 目录 时序预测 | MATLAB实现LSTM时间序列未来多步预测-递归预测基本介绍程序设计参考资料 基本介绍 MATLAB实现LSTM时间序列未来多步预测-递归预测。LSTM是一种含有LSTM区块(blocks)或其他的一种类神经网络,文献或其他资料中LSTM区块可能被描述成智能网络单元,因为

vue项目集成CanvasEditor实现Word在线编辑器

CanvasEditor实现Word在线编辑器 官网文档:https://hufe.club/canvas-editor-docs/guide/schema.html 源码地址:https://github.com/Hufe921/canvas-editor 前提声明: 由于CanvasEditor目前不支持vue、react 等框架开箱即用版,所以需要我们去Git下载源码,拿到其中两个主

android 免费短信验证功能

没有太复杂的使用的话,功能实现比较简单粗暴。 在www.mob.com网站中可以申请使用免费短信验证功能。 步骤: 1.注册登录。 2.选择“短信验证码SDK” 3.下载对应的sdk包,我这是选studio的。 4.从头像那进入后台并创建短信验证应用,获取到key跟secret 5.根据技术文档操作(initSDK方法写在setContentView上面) 6.关键:在有用到的Mo

android一键分享功能部分实现

为什么叫做部分实现呢,其实是我只实现一部分的分享。如新浪微博,那还有没去实现的是微信分享。还有一部分奇怪的问题:我QQ分享跟QQ空间的分享功能,我都没配置key那些都是原本集成就有的key也可以实现分享,谁清楚的麻烦详解下。 实现分享功能我们可以去www.mob.com这个网站集成。免费的,而且还有短信验证功能。等这分享研究完后就研究下短信验证功能。 开始实现步骤(新浪分享,以下是本人自己实现

Android我的二维码扫描功能发展史(完整)

最近在研究下二维码扫描功能,跟据从网上查阅的资料到自己勉强已实现扫描功能来一一介绍我的二维码扫描功能实现的发展历程: 首页通过网络搜索发现做android二维码扫描功能看去都是基于google的ZXing项目开发。 2、搜索怎么使用ZXing实现自己的二维码扫描:从网上下载ZXing-2.2.zip以及core-2.2-source.jar文件,分别解压两个文件。然后把.jar解压出来的整个c

基于Springboot + vue 的抗疫物质管理系统的设计与实现

目录 📚 前言 📑摘要 📑系统流程 📚 系统架构设计 📚 数据库设计 📚 系统功能的具体实现    💬 系统登录注册 系统登录 登录界面   用户添加  💬 抗疫列表展示模块     区域信息管理 添加物资详情 抗疫物资列表展示 抗疫物资申请 抗疫物资审核 ✒️ 源码实现 💖 源码获取 😁 联系方式 📚 前言 📑博客主页:

探索蓝牙协议的奥秘:用ESP32实现高质量蓝牙音频传输

蓝牙(Bluetooth)是一种短距离无线通信技术,广泛应用于各种电子设备之间的数据传输。自1994年由爱立信公司首次提出以来,蓝牙技术已经经历了多个版本的更新和改进。本文将详细介绍蓝牙协议,并通过一个具体的项目——使用ESP32实现蓝牙音频传输,来展示蓝牙协议的实际应用及其优点。 蓝牙协议概述 蓝牙协议栈 蓝牙协议栈是蓝牙技术的核心,定义了蓝牙设备之间如何进行通信。蓝牙协议