当前位置: 首页 > news >正文

磨皮功能 C++/C的OpenCV 实现

磨皮功能 C++/C的OpenCV 实现

前提条件

  1. OpenCV 安装: 你需要正确安装 OpenCV 库。
  2. C++ 编译器: 如 G++。

C++ 代码

#include <opencv2/opencv.hpp>
#include <iostream>
#include <string>// 使用标准命名空间
using namespace std;
using namespace cv;/*** @brief 对图像进行简单的磨皮处理 (使用双边滤波器)** @param inputImage 输入的彩色图像* @param d 滤波过程中每个像素邻域的直径。如果此值为非正数,则从 sigmaSpace 计算得到。* @param sigmaColor 颜色空间滤波器的 sigma 值。这个参数的值越大,就意味着在邻域内有越宽广的颜色会被混合到一起,产生较大的半相等颜色区域。* @param sigmaSpace 坐标空间滤波器的 sigma 值。这个参数的值越大,就意味着越远的像素会相互影响,从而使更大的区域中足够相似的颜色获取相同的颜色。当 d>0 时,d 指定了邻域大小且与 sigmaSpace 无关。否则,d 正比于 sigmaSpace。* @return Mat 返回磨皮后的图像*/
Mat simpleSkinSmoothing(const Mat& inputImage, int d = 15, double sigmaColor = 150, double sigmaSpace = 15) {if (inputImage.empty()) {cerr << "错误: 输入图像为空!" << endl;return inputImage;}Mat smoothedImage;bilateralFilter(inputImage, smoothedImage, d, sigmaColor, sigmaSpace);return smoothedImage;
}int main(int argc, char** argv) {// --- 1. 加载图像 ---string image_path = "portrait.jpg"; // 修改为你的肖像图片路径if (argc > 1) {image_path = argv[1]; // 或者从命令行参数获取图片路径}Mat originalImage = imread(image_path, IMREAD_COLOR);if (originalImage.empty()) {cout << "无法加载图像: " << image_path << endl;return -1;}cout << "图像加载成功: " << image_path << endl;// --- 2. 应用磨皮处理 ---// 调整这些参数以获得不同的磨皮效果int diameter = 15;          // 邻域直径。可以尝试 5, 10, 15, 20, 25 等double sigma_color = 75;   // 颜色标准差。可以尝试 50, 75, 100, 150 等double sigma_space = 75;   // 空间标准差。可以尝试 50, 75, 100, 150 等cout << "应用磨皮效果: d=" << diameter << ", sigmaColor=" << sigma_color << ", sigmaSpace=" << sigma_space << endl;Mat smoothedImage = simpleSkinSmoothing(originalImage, diameter, sigma_color, sigma_space);if (smoothedImage.empty()) {cout << "磨皮处理失败。" << endl;return -1;}// --- 3. 显示结果 ---namedWindow("原始图像", WINDOW_AUTOSIZE);imshow("原始图像", originalImage);namedWindow("简单磨皮效果", WINDOW_AUTOSIZE);imshow("简单磨皮效果", smoothedImage);cout << "按任意键退出..." << endl;waitKey(0); // 等待按键destroyAllWindows(); // 关闭所有窗口return 0;
}

如何编译

  1. 保存代码: 将上述代码保存为 skin_smoother.cpp

  2. 准备图片: 准备一张名为 portrait.jpg (或你在代码中指定的其他名称,或通过命令行传入) 的肖像图片,并将其放在与 skin_smoother.cpp 相同的目录下或指定正确路径。

  3. 编译:
    打开终端,使用以下命令编译 (假设你使用的是 g++,并且 OpenCV 已正确安装):

    g++ skin_smoother.cpp -o skin_smoother $(pkg-config --cflags --libs opencv4)
    
    • 注意: opencv4 可能需要根据你的 OpenCV 版本调整 (例如 opencvopencv3)。你可以通过运行 pkg-config --libs opencv4 来检查正确的链接标志。

如何运行

./skin_smoother

或者,如果你想指定图片路径:

./skin_smoother /path/to/your/portrait_image.jpg

程序会显示原始图像和磨皮后的图像。


代码解释

  1. 包含头文件

    #include <opencv2/opencv.hpp> // OpenCV 主要头文件
    #include <iostream>           // 标准输入输出
    #include <string>             // STL string
    
  2. simpleSkinSmoothing 函数

    Mat simpleSkinSmoothing(const Mat& inputImage, int d = 15, double sigmaColor = 150, double sigmaSpace = 15) {if (inputImage.empty()) { /* ... 错误处理 ... */ }Mat smoothedImage;// 应用双边滤波器bilateralFilter(inputImage, smoothedImage, d, sigmaColor, sigmaSpace);return smoothedImage;
    }
    
    • 这是核心的磨皮函数。它接收一个输入图像和双边滤波器的三个主要参数。
    • cv::bilateralFilter(): 这是 OpenCV 中实现双边滤波的函数。
      • inputImage: 输入图像。
      • smoothedImage: 输出的滤波后图像。
      • d: 滤波过程中每个像素邻域的直径。值越大,计算越慢,但平滑区域会更大。
      • sigmaColor: 颜色空间的标准差。值越大,意味着颜色差异更大的像素也会被一起平滑。
      • sigmaSpace: 坐标空间的标准差。值越大,意味着距离更远的像素也会相互影响(如果它们的颜色相似的话)。
  3. main 函数

    • 加载图像 (imread): 加载用户指定的或默认的图像。
    • 调用磨皮函数:
      int diameter = 15;
      double sigma_color = 75;
      double sigma_space = 75;
      Mat smoothedImage = simpleSkinSmoothing(originalImage, diameter, sigma_color, sigma_space);
      
      这里设置了双边滤波器的参数。你可以调整这些值来观察不同的磨皮效果。
    • 显示图像 (imshow, waitKey): 显示原始图像和处理后的图像,并等待用户按键关闭。

参数调整技巧

  • d (直径):
    • 较小的值 (如 5-10):平滑效果较弱,保留更多细节,计算速度快。
    • 较大的值 (如 15-25 或更高):平滑效果更强,可能导致一些细节丢失,计算速度慢。对于高分辨率图像,可能需要更大的 d
  • sigmaColor (颜色标准差):
    • 较小的值 (如 25-50):只有颜色非常相近的像素才会被平滑,保留更多纹理。
    • 较大的值 (如 75-150 或更高):颜色差异较大的像素也会被平滑,导致更强的“涂抹”感,皮肤看起来更“干净”。
  • sigmaSpace (空间标准差):
    • 较小的值 (如 25-50):只有空间上非常接近的像素才会被一起考虑,效果更局部。
    • 较大的值 (如 75-150 或更高):空间上较远的像素也会参与计算(如果颜色相似),平滑范围更广。

经验法则:

  • 通常 sigmaColorsigmaSpace 会取相似的值。
  • 可以从 d=15, sigmaColor=75, sigmaSpace=75 开始尝试。
  • 如果希望保留更多细节,减小这些值。
  • 如果希望获得更强的平滑效果,增大这些值。
  • 过度增大会导致图像看起来不自然,像塑料娃娃。

局限性

  • 简单性: 这种方法非常基础,对于复杂的皮肤问题(如严重的痘痘、斑点或光照不均)可能效果有限。
  • 全局性: 双边滤波器是全局应用的。如果只想对特定区域(如脸部皮肤)进行磨皮,需要先进行人脸检测和皮肤区域分割。
  • 细节保留: 虽然双边滤波器比高斯模糊能更好地保留边缘,但非常强的磨皮参数仍然可能导致一些期望的细节(如痣、雀斑,如果想保留的话)模糊。
  • 性能: 对于大图像和较大的 d 值,双边滤波计算可能会比较慢。

对于更高级的磨皮效果,可能需要结合频率分离、表面模糊、更复杂的皮肤检测和遮罩技术,甚至深度学习方法。但对于快速实现一个简单的磨皮效果,双边滤波器是一个很好的起点。

相关文章:

  • 【11408学习记录】考研英语写作提分秘籍:2013真题邀请信精讲+万能模板套用技巧
  • 【shell】通过Shell命令占用内存
  • 利用python工具you-get下载网页的视频文件
  • #AI短视频制作完整教程
  • JDK21深度解密 Day 9:响应式编程模型重构
  • CTFHub-RCE 命令注入-过滤目录分隔符
  • 小明的Java面试奇遇之互联网保险系统架构与性能优化
  • 性能优化 - 理论篇:CPU、内存、I/O诊断手段
  • Unity3D仿星露谷物语开发57之保存库存信息到文件
  • 精简多功能办公软件
  • CodeTop100 Day18
  • 用 Pandera 高效验证和清洗 Pandas 数据集——实用分步指南
  • offset三大家族
  • stm32默认复位刚开始由hsi作为主时钟源而后来才换成的pll
  • 硬件开发全解:从入门教程到实战案例与丰富项目资源
  • 【深度学习】14. DL在CV中的应用章:目标检测: R-CNN, Fast R-CNN, Faster R-CNN, MASK R-CNN
  • Python实现P-PSO优化算法优化循环神经网络LSTM分类模型项目实战
  • day23-计算机网络-1
  • Deepin 23.10安装Docker
  • Rk3568驱动开发_GPIO点亮LED_12
  • 网页设计网站布局分析/谷歌seo网站优化
  • 网站买空间的价格/今日热点新闻事件2022
  • 那家b2c网站建设报价/四川企业seo
  • 关于网站建设外文文献/软文推广名词解释
  • fedora做网站服务器/营销渠道模式有哪些
  • 网站二级分类/站长之家官网