基于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

相关文章

golang版本升级如何实现

《golang版本升级如何实现》:本文主要介绍golang版本升级如何实现问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录golanwww.chinasem.cng版本升级linux上golang版本升级删除golang旧版本安装golang最新版本总结gola

SpringBoot中SM2公钥加密、私钥解密的实现示例详解

《SpringBoot中SM2公钥加密、私钥解密的实现示例详解》本文介绍了如何在SpringBoot项目中实现SM2公钥加密和私钥解密的功能,通过使用Hutool库和BouncyCastle依赖,简化... 目录一、前言1、加密信息(示例)2、加密结果(示例)二、实现代码1、yml文件配置2、创建SM2工具

Mysql实现范围分区表(新增、删除、重组、查看)

《Mysql实现范围分区表(新增、删除、重组、查看)》MySQL分区表的四种类型(范围、哈希、列表、键值),主要介绍了范围分区的创建、查询、添加、删除及重组织操作,具有一定的参考价值,感兴趣的可以了解... 目录一、mysql分区表分类二、范围分区(Range Partitioning1、新建分区表:2、分

MySQL 定时新增分区的实现示例

《MySQL定时新增分区的实现示例》本文主要介绍了通过存储过程和定时任务实现MySQL分区的自动创建,解决大数据量下手动维护的繁琐问题,具有一定的参考价值,感兴趣的可以了解一下... mysql创建好分区之后,有时候会需要自动创建分区。比如,一些表数据量非常大,有些数据是热点数据,按照日期分区MululbU

MySQL中查找重复值的实现

《MySQL中查找重复值的实现》查找重复值是一项常见需求,比如在数据清理、数据分析、数据质量检查等场景下,我们常常需要找出表中某列或多列的重复值,具有一定的参考价值,感兴趣的可以了解一下... 目录技术背景实现步骤方法一:使用GROUP BY和HAVING子句方法二:仅返回重复值方法三:返回完整记录方法四:

IDEA中新建/切换Git分支的实现步骤

《IDEA中新建/切换Git分支的实现步骤》本文主要介绍了IDEA中新建/切换Git分支的实现步骤,通过菜单创建新分支并选择是否切换,创建后在Git详情或右键Checkout中切换分支,感兴趣的可以了... 前提:项目已被Git托管1、点击上方栏Git->NewBrancjsh...2、输入新的分支的

Python实现对阿里云OSS对象存储的操作详解

《Python实现对阿里云OSS对象存储的操作详解》这篇文章主要为大家详细介绍了Python实现对阿里云OSS对象存储的操作相关知识,包括连接,上传,下载,列举等功能,感兴趣的小伙伴可以了解下... 目录一、直接使用代码二、详细使用1. 环境准备2. 初始化配置3. bucket配置创建4. 文件上传到os

关于集合与数组转换实现方法

《关于集合与数组转换实现方法》:本文主要介绍关于集合与数组转换实现方法,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、Arrays.asList()1.1、方法作用1.2、内部实现1.3、修改元素的影响1.4、注意事项2、list.toArray()2.1、方

使用Python实现可恢复式多线程下载器

《使用Python实现可恢复式多线程下载器》在数字时代,大文件下载已成为日常操作,本文将手把手教你用Python打造专业级下载器,实现断点续传,多线程加速,速度限制等功能,感兴趣的小伙伴可以了解下... 目录一、智能续传:从崩溃边缘抢救进度二、多线程加速:榨干网络带宽三、速度控制:做网络的好邻居四、终端交互

mysql表操作与查询功能详解

《mysql表操作与查询功能详解》本文系统讲解MySQL表操作与查询,涵盖创建、修改、复制表语法,基本查询结构及WHERE、GROUPBY等子句,本文结合实例代码给大家介绍的非常详细,感兴趣的朋友跟随... 目录01.表的操作1.1表操作概览1.2创建表1.3修改表1.4复制表02.基本查询操作2.1 SE