【SRC-CPP-OpenCV】给图片更换背景色

文章目录

  • Part.I Introduction
  • Part.II Main_body
    • Chap.I 源码简析
    • Chap.II 效果展示
  • Part.III 源码
  • Reference

Part.I Introduction

本文将介绍如何用 OpenCV 更换图片的背景色(附有完整代码)。

Part.II Main_body

Chap.I 源码简析

配置部分:包括输入文件名、输出文件名、需要更换的背景色(可以尝试随机背景色)

	string filename_in = "A:/OHanlon/Desktop/1017451354889.png";string filename_out = "A:/OHanlon/Desktop/a.png";Vec3b color;    // 设置的背景色RNG rng(12345);color[0] = 255; // rng.uniform(0, 255);color[1] = 255; // rng.uniform(0, 255);color[2] = 255; // rng.uniform(0, 255);

数据处理部分的流程大致如下:

  1. 将二维图像数据线性化
  2. 使用 K-means 聚类;分离出背景色
  3. 背景与前景二值化
  4. 腐蚀 + 高斯模糊:图像与背景交汇处高斯模糊化
  5. 更换背景色以及交汇处融合处理

调用 OpenCV 里面的主要的函数

// k 均值聚类
kmeans(data, numCluster, labels, criteria, 3, KMEANS_PP_CENTERS);
// 高斯模糊
GaussianBlur(mask, mask, Size(3, 3), 0, 0);

Chap.II 效果展示

示例一:

在这里插入图片描述
存在如下几个问题:

  1. 图片中的文字和箭头也被当作背景给消掉了
  2. 非背景和背景的边缘有些模糊,可能做了模糊处理,有可能原图的分辨率就很低

示例二

在这里插入图片描述
这个还不错

Part.III 源码

整个源码如下:

#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui_c.h>using namespace std;
using namespace cv;bool _changeBackgroundColor()
{
#pragma region BASIC Configurationstring filename_in = "A:/OHanlon/Desktop/1017451354889.png";string filename_out = "A:/OHanlon/Desktop/a.png";Vec3b color;    // 设置的背景色RNG rng(12345);color[0] = 255; // b rng.uniform(0, 255);color[1] = 255; // g rng.uniform(0, 255);color[2] = 255; // r rng.uniform(0, 255);
#pragma endregion#pragma region ProcessingMat src = imread(filename_in);if (src.empty()) {printf("could not load image...\n");return false;}namedWindow("原图", 0);cvResizeWindow("原图", 500, 500);imshow("原图", src);// 1.将二维图像数据线性化Mat data;for (int i = 0; i < src.rows; i++)     //像素点线性排列for (int j = 0; j < src.cols; j++){Vec3b point = src.at<Vec3b>(i, j);Mat tmp = (Mat_<float>(1, 3) << point[0], point[1], point[2]);data.push_back(tmp);}// 2.使用K-means聚类;分离出背景色int numCluster = 4;Mat labels;TermCriteria criteria = TermCriteria(TermCriteria::EPS + TermCriteria::COUNT, 10, 0.1);kmeans(data, numCluster, labels, criteria, 3, KMEANS_PP_CENTERS);// 3.背景与人物二值化Mat mask = Mat::zeros(src.size(), CV_8UC1);int index = src.rows * 2 + 2;  //获取点(2,2)作为背景色int cindex = labels.at<int>(index);/*  提取背景特征 */for (int row = 0; row < src.rows; row++){for (int col = 0; col < src.cols; col++){index = row * src.cols + col;int label = labels.at<int>(index);if (label == cindex) { // 背景mask.at<uchar>(row, col) = 0;}else {mask.at<uchar>(row, col) = 255;}}}//imshow("mask", mask);// 4.腐蚀 + 高斯模糊:图像与背景交汇处高斯模糊化Mat k = getStructuringElement(MORPH_RECT, Size(3, 3), Point(-1, -1));erode(mask, mask, k);//imshow("erode-mask", mask);GaussianBlur(mask, mask, Size(3, 3), 0, 0);//imshow("Blur Mask", mask);// 5.更换背景色以及交汇处融合处理Mat result(src.size(), src.type());double w = 0.0;   //融合权重int b = 0, g = 0, r = 0;int b1 = 0, g1 = 0, r1 = 0;int b2 = 0, g2 = 0, r2 = 0;for (int row = 0; row < src.rows; row++){for (int col = 0; col < src.cols; col++){int m = mask.at<uchar>(row, col);if (m == 255) {result.at<Vec3b>(row, col) = src.at<Vec3b>(row, col); // 前景}else if (m == 0) {result.at<Vec3b>(row, col) = color; // 背景}else {/* 融合处理部分 */w = m / 255.0;b1 = src.at<Vec3b>(row, col)[0];g1 = src.at<Vec3b>(row, col)[1];r1 = src.at<Vec3b>(row, col)[2];b2 = color[0];g2 = color[1];r2 = color[2];b = b1 * w + b2 * (1.0 - w);g = g1 * w + g2 * (1.0 - w);r = r1 * w + r2 * (1.0 - w);result.at<Vec3b>(row, col)[0] = b;result.at<Vec3b>(row, col)[1] = g;result.at<Vec3b>(row, col)[2] = r;}}}
#pragma endregionnamedWindow("背景替换", 0);cvResizeWindow("背景替换", 500, 500);imshow("背景替换", result);imwrite(filename_out, result);waitKey(0);return true;
}

Reference

  • OpenCV案例(五): 更换背景色

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/11614.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java文字识别接口、票据ocr、接口开发文档

曾经看到过这样一句话“如果把产品比作孩子的话&#xff0c;那么产品经理就是生孩子的”。由此可见&#xff0c;产品经理对于产品的重要性。一位有经验的产品经理提出的产品需求往往逻辑清晰&#xff0c;技术开发过程中修改需求的次数少&#xff0c;产品上线、推出后让人易于接…

uniapp:项目目录下没有package.json文件的创建办法

问题 在HbuilderX开发工具创建的uniapp项目&#xff0c;默认没有package.json文件。 此时如果在控制台使用npm 命令添加外部依赖包时&#xff0c;就会出现“no such file or directory *** package.json ”的提示错误。 解决方案 在控制台使用npm 命令&#xff0c;进行初始…

1-3ARM_GD32点亮LED灯

简介&#xff1a; 最多可支持 112 个通用 I/O 引脚(GPIO)&#xff0c;分别为 PA0 ~ PA15&#xff0c;PB0 ~ PB15&#xff0c;PC0 ~ PC15&#xff0c;PD0 ~ PD15&#xff0c;PE0 ~ PE15&#xff0c;PF0 ~ PF15 和 PG0 ~ PG15&#xff0c;各片上设备用其来实现逻辑输入/输出功能。…

【论文精读】| KBS2023-TMBL-多模态情感分析系列文章解读

TMBL: Transformer-based multimodal binding learning model for multimodal sentiment analysis 一. KBS2023-TMBL-用于多模态情感分析的极向量和强度向量混合器模型1 Abstract1.1 Motivation1.2 Method1.3 Results 2. Related Work2.1 情感分析2.1 基于transformer的2.1 模态…

字符数组(字符串):单词计数

字符数组 定义 初始化 : 单个字符初始化 用字符串常量初始化 输入输出 &#xff1a; %s 不能够获得带有分隔符的串 存储特点 结束标记&#xff08;\0) #include<stdio.h> #include<stdlib.h>#define N 32int main(){char str[N] {a,b,c};chr str0[N],str1[N],str…

LeetCode/NowCoder-链表经典算法OJ练习2

最好的&#xff0c;不一定是最合适的&#xff1b;最合适的&#xff0c;才是真正最好的。&#x1f493;&#x1f493;&#x1f493; 目录 说在前面 题目一&#xff1a;分割链表 题目二&#xff1a;环形链表的约瑟夫问题 SUMUP结尾 说在前面 dear朋友们大家好&#xff01;&…

(done) 什么是马尔可夫链?Markov Chain

参考视频&#xff1a;https://www.bilibili.com/video/BV1ko4y1P7Zv/?spm_id_from333.337.search-card.all.click&vd_source7a1a0bc74158c6993c7355c5490fc600 如下图所示&#xff0c;马尔可夫链条实际上就是 “状态机”&#xff0c;只不过状态机里不同状态之间的边上是 “…

车载电子电器架构 —— Vector对于车载以太网的解决方案(协议栈)

车载电子电器架构 —— Vector对于车载以太网的解决方案(协议栈) 我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 屏蔽力是信息过载时代一个人的特殊竞争力,任何消耗你的人和事,多看一眼都是你…

实战WinRAR捆绑图片和恶意程序并自动上线Cobalt Strike(cs钓鱼日记)

钓鱼 - WinRAR捆绑图片和恶意程序并自动上线Cobalt Strike 环境准备 工具&#xff1a;Cobalt Strike、Winrar压缩工具、一张JPG图片 虚拟机IP&#xff1a; 【攻击机】Kali&#xff1a;192.168.232.128 【靶机】win7&#xff1a;192.168.232.144 情景&#xff1a;在钓鱼事…

老黄终于不穿皮衣了,分享一个AI换装AI试衣软件!

用AI实现在线试衣&#xff0c;或者在线换装&#xff0c;这不是一个新概念&#xff0c;肯定有人这么想过&#xff0c;但并不是所有人能都能轻松做到啊&#xff01; 今天就来分享一个人人都可以实现的方法&#xff0c;而且是那种傻瓜式的不用付钱的那种&#xff0c;甚至可以把软件…

大数据在IT行业的应用与发展趋势及IT行业的现状与未来

大数据在IT行业中的应用、发展趋势及IT行业的现状与未来 一、引言 随着科技的飞速发展&#xff0c;大数据已经成为IT行业的重要驱动力。从数据收集、存储、处理到分析&#xff0c;大数据技术为各行各业带来了深远的影响。本文将详细探讨大数据在IT行业中的应用、发展趋势&#…

ArrayList源码解析

目录 数组 大小 默认容量和最小容量 构造函数 add(E e) get(int index)

详解依赖注入的三种方法以及遇到问题的解决

各位大佬光临寒舍&#xff0c;希望各位能赏脸给个三连&#xff0c;谢谢各位大佬了&#xff01;&#xff01;&#xff01; 目录 1.三种依赖注入的方法 1.属性注入 优点 缺点 2.构造方法注入 优点 缺点 3.Setter注入 优点 缺点 4.小结 2.依赖注入常见问题的解决 1…

如何不用额外变量交换两个数

int a 19int b 33 交换 正常代码 int a 19;int b 33;int tmp 0;tmp a;a b;b tmp; 这个代码都见过&#xff0c;都写过 使用如下代码 int a 19;int b 33;a a ^ b;b a ^ b;a a ^ b;System.out.println(a);System.out.println(b); 分析 假设a x ; b y; a a ^ b…

图层遮盖判定算法实现2

图层遮盖判定算法实现2 1. 点击时调用置灰2. 解决方式 图层遮盖判定算法实现2 学习于bilibili 尚学堂官方 1. 点击时调用置灰 在Brand中 if (brand.getGray()){//灰色return;}else {brand.getParent().remove(brand);//通过父容器删掉自己 一般树形结构使用此方式//也需要…

linux Nginx安装与启动

一、先到官网下载Nginx 官网地址&#xff1a; http://nginx.org/en/download.html 我下载的是nginx-1.20.2 二、下载好的文件上传到服务器&#xff0c;然后解压 1、上传到指定的服务器地址&#xff0c;我这里是公司服务器&#xff0c;目录都是定义好的&#xff0c;自己玩建…

Flutter 中的 ToggleButtons 小部件:全面指南

Flutter 中的 ToggleButtons 小部件&#xff1a;全面指南 在 Flutter 中&#xff0c;ToggleButtons 是一种允许用户在一组选项中进行切换选择的控件。它通常用于展示一组相关选项&#xff0c;让用户可以快速切换选择。ToggleButtons 是一种水平排列的按钮集合&#xff0c;其中…

数据结构与算法学习笔记之线性表五---循环链表的表示和实现(C++)

目录 前言 1.双向链表的定义 2.双向链表的表示和实现 1.定义 2.初始化 3.销毁 4.清空 5.表长 6.获取数据元素 7.前驱节点 8.后继节点 9.插入 10.删除 11.遍历 12.完整代码 前言 记录下双向链表的表示和实现。 1.循环链表的定义 循环链表(circular linked list)…

The Onion Router-洋葱

目录 Tor的运作原理 Tor挑战和局限性 Tor&#xff0c;即The Onion Router&#xff08;洋葱路由器&#xff09;&#xff0c;是一个用于匿名通信的开放网络&#xff0c;它旨在增强用户的隐私和安全。Tor的名字源自其设计原理&#xff0c;类似于将信息包装在多层“洋葱”中&…

本来还挺喜欢……

前阵子买了个天空星开发板&#xff0c;到手之后发觉不对劲。 之前我们玩玩开发板都是用的面包板的&#xff0c;就算是ESP那种比较宽的板子用两个面包板拼一下也勉强可以用。 但是天空星它的引脚是分为两组&#xff0c;每组有两排&#xff0c;如果我们还是直接使用面包板的话&a…