java-正装照换底色小demo-技术分享

文章目录

  • 前言
      • java-正装照换底色小demo-技术分享
        • 01 实现思路
        • 02 效果
          • 02::01 原图:
          • 02::02 执行单元测试:
          • 02::03 效果:
        • 03 编码实现

前言

  如果您觉得有用的话,记得给博主点个赞,评论,收藏一键三连啊,写作不易啊^ _ ^。
  而且听说点赞的人每天的运气都不会太差,实在白嫖的话,那欢迎常来啊!!!


java-正装照换底色小demo-技术分享

本来闲着没事想写个小demo玩玩,结果没想到坑还挺多,写个博客记录一下。

01 实现思路

其实这个需求如果加上人脸识别的话,然后截取人像部分,替换背景色,应该是最佳的选择。
而我的思路就只用java的awt包来解决,可能对于那些不是很标准的正装照来说,可能会有些瑕疵,但对于那些标签的正装照来说,是没有问题的。
下面是我的实现思路:

  1. 获取目标图片流;
  2. 取左上角30-30的位置作为图片原始背景色,即我们要替换的背景色;
  3. 遍历图片的像素(遍历长和宽上的每个像素),把指定像素上的颜色换成目标颜色;
  4. 当出现第一次出现指定像素上的颜色与图像上颜色不一致的时候,进行第二次范围RGB范围判断,因为有些正装照的背景色,不太标准,背景色有可能有些地方虽然都在 一个色素的范围之内,肉眼难以辨别,但是有可能有些差异,所以我又加了一个像素范围的过滤,判断图像上的颜色是否在这个指定像素范围之内, 如果在范围之内,那么替换目标像素,当第三次出现指定像素上的颜色与图像上颜色不一致的时候,不走范围RGB判断,因为如果没有控制的话, 可能将人物衣服上某些不该替换的颜色被目标颜色替换;
  5. 将修改完的图片生成新的图片文件输出;

02 效果

02::01 原图:

在这里插入图片描述

02::02 执行单元测试:
public  class PhotographToColorTest {

    @Test
    public void test(){
        String path = "D:\\Photograph\\证件照测试.jpg";

        //红色
        PhotographToColor.imageBackgroundRGB(path,PhotographToColor.TYPE.RED);
        //蓝色
        PhotographToColor.imageBackgroundRGB(path,PhotographToColor.TYPE.BLUE);
    }

}

在这里插入图片描述

02::03 效果:

在这里插入图片描述

在这里插入图片描述
毕竟拿的是网图,这个正装照有些地方不是很标准,如果是标准的正装照,背景色素是一样的,使用这个办法就没有问题。


03 编码实现

引用:

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;

具体小demo实现:

/**
 * @author yangzhenyu
 * @version 1.0
 * @description:
 * @date 2023/3/10 10:20
 */

public class PhotographToColor {


    private final static String BLUE = "BLUE";
    private final static String RED = "RED";
    private final static String WHITE ="WHITE";

    private static Map<String,PhotographToColor.RGB> init =   new ConcurrentHashMap<>();

    static {
        init.put(BLUE,new PhotographToColor.RGB(0,0,255));
        init.put(RED,new PhotographToColor.RGB(255,0,0));
        init.put(WHITE,new PhotographToColor.RGB(255,255,255));

    }
    private static final Logger log = LoggerFactory.getLogger(PhotographToColor.class);
    private static final int CRITICAL = 30;
    private static final int NUM = 1;

    // int转rgb
    public static String converArgbToRgb(int argb){
        int [] rgb  = new int[3];
        rgb[0] = (argb & 0xff0000) >> 16;
        rgb[1] = (argb & 0xff00) >> 8;
        rgb[2] = (argb & 0xff);
        return "rgb("+rgb[0]+","+rgb[1]+","+rgb[2]+")";
    }
    // rgb转int
    public static int rgbToArgb(int r,int g,int b){
        return ((0xFF << 24)|(r << 16)|(g << 8)|b);
    }

    public static int rule(int nowR,int nowG,int nowB,int p,int targetRgb){
        //蓝色
        if(nowR<188&&nowR>-1 && nowG<256&&nowG>133 && nowB<256&&nowB>204 ) {
            p = targetRgb;
        }
        //白色
        if(nowR<256&&nowR>240 && nowG<256&&nowG>240 && nowB<256&&nowB>240 ) {
            p = targetRgb;
        }
        //红色
        if(nowR<256&&nowR>149 && nowG<107&&nowG>-1 && nowB<100&&nowB>-1 ) {
            p = targetRgb;
        }

        return p;

    }
    /***
     * 处理图片背景色
     * @param path 原图地址
     */
    public static void imageBackgroundRGB(String path,PhotographToColor.TYPE type)  {
        RGB rgb = init.get(type.code);
        int targetRgb = rgbToArgb(rgb.getR(),rgb.getG(),rgb.getB());
        File file = new File(path);
        //格式
        String[] data = path.split("\\.");
        String format = data [1];
        //输出的路径
        String srcPath = StringUtils.join(data[0], "_", UUID.randomUUID(),".", format);
        File srcPathFile = new File(srcPath);
        //用来处理图片的缓冲流
        BufferedImage bi = null;
        BufferedImage image = null;

        try {
            //用ImageIO将图片读入到缓冲中
            bi = ImageIO.read(file);
            //得到图片的长宽
            int width = bi.getWidth();
            int height = bi.getHeight();
            image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);

            // 获取左上角颜色,默认左上角像素块颜色为背景色
            int pixel = bi.getRGB(CRITICAL, CRITICAL);
            String s = converArgbToRgb(pixel);
            log.info("=============="+s);
            log.info("图片名称:{}, targetRgb:{}, width:{}, height:{}, pixel:{}",
                    file.getName(), targetRgb, width, height, pixel);
            /**
             * 这里是遍历图片的像素,因为要处理图片的背色,所以要把指定像素上的颜色换成目标颜色
             * 这里 是一个二层循环,遍历长和宽上的每个像素
             */
            Graphics graphics = image.getGraphics();
            Boolean flag =Boolean.FALSE;
            int num = 0;
            for (int x = 0; x < width; x++) {
                for (int y = 0; y < height; y++) {
                    // 得到指定像素(i,j)上的RGB值,
                    int nowPixel = bi.getRGB(x, y);
                    int p = nowPixel;
                    if (flag){
                        int nowR = (nowPixel & 0xff0000) >> 16;
                        int nowG = (nowPixel & 0xff00) >> 8;
                        int nowB = (nowPixel & 0xff);
                        p = rule(nowR,nowG,nowB,p,targetRgb);
                    }else {
                        p = pixel == nowPixel ? targetRgb : nowPixel;
                    }
                    if (targetRgb == p){
                        flag = Boolean.TRUE;
                    }else{
                        flag = Boolean.FALSE;

                    }
                    graphics.setColor(new Color(p));
                    graphics.fillRect(x, y, 1, 1);
                }
            }
            log.info("处理完毕:{}", file.getName());
            ImageIO.write(image, format, srcPathFile);
        }catch (Exception e){
            log.error("错误",e);

        }
    }

    enum TYPE{
        BLUE("BLUE"),
        RED("RED"),
        WHITE("WHITE");
        private final String code;

        TYPE(String code) {
            this.code = code;
        }

        public String getCode() {
            return code;
        }
    }
    static class RGB{
        private int r;
        private int g;
        private int b;

        public RGB(int r, int g, int b) {
            this.r = r;
            this.g = g;
            this.b = b;
        }

        public int getR() {
            return r;
        }

        public void setR(int r) {
            this.r = r;
        }

        public int getG() {
            return g;
        }

        public void setG(int g) {
            this.g = g;
        }

        public int getB() {
            return b;
        }

        public void setB(int b) {
            this.b = b;
        }
    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

js逆向爬取某音乐网站某歌手的歌曲

js逆向爬取某音乐网站某歌手的歌曲一、分析网站1、案例介绍2、寻找列表页Ajax入口&#xff08;1&#xff09;页面展示图。&#xff08;2&#xff09;寻找部分歌曲信息Ajax的token。&#xff08;3&#xff09;寻找歌曲链接&#xff08;4&#xff09;获取歌曲名称和id信息3、寻找…

XXE漏洞复现

目录XML基础概念XML数据格式DTD基础定义DTD作用分类DTD实体实体的分类DTD元素XXE漏洞介绍实操如何探测xxe漏洞XML基础 概念 什么是XML 是一种可扩展标记语言 (Extensible Markup Language, XML) &#xff0c;标准通用标记语言的子集&#xff0c;可以用来标记数据、定义数据类型…

30个题型+代码(冲刺2023蓝桥杯)(中)

2023.3.13~4.13持续更新 目录 &#x1f34e;注意 &#x1f33c;前言 &#x1f33c;十&#xff0c;KMP&#xff08;留坑&#xff09; &#x1f33c;十一&#xff0c;Trie&#xff08;留坑&#xff09; &#x1f33c;十二&#xff0c;BFS &#x1f44a;(一)1562. 微博转发…

OpenAI 发布GPT-4——全网抢先体验

OpenAI 发布GPT-4 最近 OpenAI 犹如开挂一般&#xff0c;上周才刚刚推出GPT-3.5-Turbo API&#xff0c;今天凌晨再次祭出GPT-4这个目前最先进的多模态预训练大模型。与上一代GPT3.5相比&#xff0c;GPT-4最大的飞跃是增加了识图能力&#xff0c;并且回答准确性也得到显著提高。…

写给20、21级学生的话

写给20、21级学生的话前言一、关于招聘变招生&#xff0c;你怎么看&#xff1f;二、对于即将实习/已经实习的学生&#xff0c;你有什么建议&#xff1f;1.学习方面2.提升方面三、思想成年真的很重要前言 最近&#xff0c;有一些同学遇到的实习问题&#xff0c;我统一回复下&…

第十二届蓝桥杯省赛详解

试题A&#xff1a;空间 1B是8位&#xff0c;32位二进制数占用4B空间&#xff0c;1MB2^10KB2^20B 那么可以存放32位二进制数的个数为256*2^20*8/3267108864 试题B&#xff1a;卡片 分析&#xff1a;因为数据只有2021&#xff0c;所以直接模拟即可 结果为&#xff1a;3181&…

MySQL基础------sql指令1.0(查询操作->select)

目录 前言&#xff1a; 单表查询 1.查询当前所在数据库 2.查询整个表数据 3.查询某字段 4.条件查询 5.单行处理函数&#xff08;聚合函数&#xff09; 6.查询时给字段取别名 7.模糊查询 8.查询结果去除重复项 9.排序&#xff08;升序和降序&#xff09; 10. 分组查询 1…

Linux 如何使用 git | 新建仓库 | git 三板斧

文章目录 专栏导读 一、如何安装 git 二、注册码云账号 三、新建仓库 配置仓库信息 四、克隆远端仓库到本地 五、git 三板斧 1. 三板斧第一招&#xff1a;git add 2. 三板斧第二招&#xff1a;git commit 解决首次 git commit 失败的问题 配置机器信息 3. 三…

最新!Windows 11 更新将整合 AI 技术

微软MVP实验室研究员张雅琪&#xff08;阿法兔&#xff09;微软最有价值专家&#xff08;MVP&#xff09;&#xff0c;毕业于外交学院和香港大学&#xff0c;IT 技术社区创始人&#xff0c;中关村互联网金融研究院兼职研究员&#xff0c;多次受邀在微软 Reactor 进行公开演讲&a…

电子工程师必须掌握的硬件测试仪器,你确定你都掌握了?

目录示波器示例1&#xff1a;测量示波器自带的标准方波信号输出表笔认识屏幕刻度认识波形上下/左右移动上下/左右刻度参数调整通道1的功能界面捕获信号设置Menu菜单触发方式触发电平Cursor按钮捕捉波形HLEP按钮参考资料频谱分析仪器信号发生器示波器 示例1&#xff1a;测量示波…

STM32F103R8T6 SPWM实现正弦波输出

前言 PWM合成正弦波&#xff0c;原理什么的不详细说了&#xff0c;概括一下就是 PWM有效面积的积分 正弦波的有效面积。PWM的频率越快&#xff0c;细分的越多&#xff0c;锯齿也就越不明显。 做法是&#xff1a;首先利用正弦波取点软件&#xff0c;取点1000个&#xff0c;生…

求职(怎么才算精通JAVA开发)

在找工作的的时候,有时候我们需要对自己的技术水平做一个评估。特别是Java工程师,我们该怎么去表达自己的能力和正确认识自己所处的技术水平呢。技术一般的人,一般都不敢说自己精通JAVA,因为你说了精通JAVA几乎就给了面试官一个可以随便往死里问的理由了。很多不自信的一般…

《ChatGPT是怎样炼成的》

ChatGPT 在全世界范围内风靡一时&#xff0c;我现在每天都会使用 ChatGPT 帮我回答几个问题&#xff0c;甚至有的时候在一天内我和它对话的时间比和正常人类对话还要多&#xff0c;因为它确实“法力无边&#xff0c;功能强大”。 ChatGPT 可以帮助我解读程序&#xff0c;做翻译…

在 4G 内存的机器上,申请 8G 内存会怎么样?

在 4GB 物理内存的机器上&#xff0c;申请 8G 内存会怎么样&#xff1f; 这个问题在没有前置条件下&#xff0c;就说出答案就是耍流氓。这个问题要考虑三个前置条件&#xff1a; 操作系统是 32 位的&#xff0c;还是 64 位的&#xff1f;申请完 8G 内存后会不会被使用&#x…

cmd命令教程

小提示&#xff1a; 在本文中&#xff0c;我将向您展示可以在 Windows 命令行上使用的 40 个命令 温馨提示&#xff1a;在本教程中学习使用适用于 Windows 10 和 CMD 网络命令的最常见基本 CMD 命令及其语法和示例 文章目录为什么命令提示符有用一、cmd是什么&#xff1f;如何在…

一年经验年初被裁面试1月有余无果,还遭前阿里面试官狂问八股,人麻了

最近接到一粉丝投稿&#xff1a;年初被裁员&#xff0c;在家躺平了6个月&#xff0c;然后想着学习下再去面试&#xff0c;现在面试了1个月有余&#xff0c;无果&#xff0c;天天打游戏到半夜&#xff0c;根本无法静下心来学习。下面是他这些天面试经常会被问到的一些问题&#…

手机解锁方法:8个顶级的 Android 手机解锁软件

一般来说&#xff0c;太简单的密码是不安全的&#xff0c;所以我们设置一个安全的密码&#xff0c;可能会稍微复杂一点。然而&#xff0c;我们可能经常会忘记复杂的密码并锁定我们的 Android 智能手机。 8个顶级的 Android 手机解锁软件 如果您遇到过这种情况并且正在寻找一种…

【Android -- 软技能】聊聊程序员的软技能

什么是软技能&#xff1f; 所谓软技能&#xff0c;就是相对于「硬技能」而言的技能&#xff0c;对于程序员来说&#xff0c;「硬技能」就是计算机专业技术能力&#xff0c;软技能则是专业之外的所有技能&#xff0c;包括职业规划能力、处理人际关系能力、专业态度、做事的方式…

linux基本功系列之uname实战

文章目录前言一. uname命令介绍二. 语法格式及常用选项三. 参考案例3.1 输出全部信息3.2 输出内核名称及版本3.3 输出网络节点的主机名3.4 输出主机硬件架构3.5 输出操作系统名称3.6 显示版本信息总结前言 大家好&#xff0c;又见面了&#xff0c;我是沐风晓月&#xff0c;本文…

初入了解——什么是VUE

个人简介&#xff1a;云计算网络运维专业人员&#xff0c;了解运维知识&#xff0c;掌握TCP/IP协议&#xff0c;每天分享网络运维知识与技能。座右铭&#xff1a;海不辞水&#xff0c;故能成其大&#xff1b;山不辞石&#xff0c;故能成其高。个人主页&#xff1a;小李会科技的…
最新文章