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

相关文章

SpringBoot集成redisson实现延时队列教程

《SpringBoot集成redisson实现延时队列教程》文章介绍了使用Redisson实现延迟队列的完整步骤,包括依赖导入、Redis配置、工具类封装、业务枚举定义、执行器实现、Bean创建、消费... 目录1、先给项目导入Redisson依赖2、配置redis3、创建 RedissonConfig 配

Python的Darts库实现时间序列预测

《Python的Darts库实现时间序列预测》Darts一个集统计、机器学习与深度学习模型于一体的Python时间序列预测库,本文主要介绍了Python的Darts库实现时间序列预测,感兴趣的可以了解... 目录目录一、什么是 Darts?二、安装与基本配置安装 Darts导入基础模块三、时间序列数据结构与

Python使用FastAPI实现大文件分片上传与断点续传功能

《Python使用FastAPI实现大文件分片上传与断点续传功能》大文件直传常遇到超时、网络抖动失败、失败后只能重传的问题,分片上传+断点续传可以把大文件拆成若干小块逐个上传,并在中断后从已完成分片继... 目录一、接口设计二、服务端实现(FastAPI)2.1 运行环境2.2 目录结构建议2.3 serv

C#实现千万数据秒级导入的代码

《C#实现千万数据秒级导入的代码》在实际开发中excel导入很常见,现代社会中很容易遇到大数据处理业务,所以本文我就给大家分享一下千万数据秒级导入怎么实现,文中有详细的代码示例供大家参考,需要的朋友可... 目录前言一、数据存储二、处理逻辑优化前代码处理逻辑优化后的代码总结前言在实际开发中excel导入很

SpringBoot+RustFS 实现文件切片极速上传的实例代码

《SpringBoot+RustFS实现文件切片极速上传的实例代码》本文介绍利用SpringBoot和RustFS构建高性能文件切片上传系统,实现大文件秒传、断点续传和分片上传等功能,具有一定的参考... 目录一、为什么选择 RustFS + SpringBoot?二、环境准备与部署2.1 安装 RustF

Nginx部署HTTP/3的实现步骤

《Nginx部署HTTP/3的实现步骤》本文介绍了在Nginx中部署HTTP/3的详细步骤,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学... 目录前提条件第一步:安装必要的依赖库第二步:获取并构建 BoringSSL第三步:获取 Nginx

MyBatis Plus实现时间字段自动填充的完整方案

《MyBatisPlus实现时间字段自动填充的完整方案》在日常开发中,我们经常需要记录数据的创建时间和更新时间,传统的做法是在每次插入或更新操作时手动设置这些时间字段,这种方式不仅繁琐,还容易遗漏,... 目录前言解决目标技术栈实现步骤1. 实体类注解配置2. 创建元数据处理器3. 服务层代码优化填充机制详

Python实现Excel批量样式修改器(附完整代码)

《Python实现Excel批量样式修改器(附完整代码)》这篇文章主要为大家详细介绍了如何使用Python实现一个Excel批量样式修改器,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一... 目录前言功能特性核心功能界面特性系统要求安装说明使用指南基本操作流程高级功能技术实现核心技术栈关键函

Java实现字节字符转bcd编码

《Java实现字节字符转bcd编码》BCD是一种将十进制数字编码为二进制的表示方式,常用于数字显示和存储,本文将介绍如何在Java中实现字节字符转BCD码的过程,需要的小伙伴可以了解下... 目录前言BCD码是什么Java实现字节转bcd编码方法补充总结前言BCD码(Binary-Coded Decima

SpringBoot全局域名替换的实现

《SpringBoot全局域名替换的实现》本文主要介绍了SpringBoot全局域名替换的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一... 目录 项目结构⚙️ 配置文件application.yml️ 配置类AppProperties.Ja