美文网首页程序人生程序员实用工具
用Java和OpenCV生成Github默认头像

用Java和OpenCV生成Github默认头像

作者: Kindem | 来源:发表于2018-02-24 14:58 被阅读276次

    转自Kindem的博客

    前言

    刚刚过完年,把这样那样的事情忙完,就赶紧把博客剩下的主要功能都先做完了,感觉一身轻松。

    闲下来了就抽空看看Github上的项目,偶然间发现Github的默认头像很有特色,它并不像其它的网站一样使用一张默认图片,而是临时随机生成一张,很有特色,看起来也挺好玩的,于是就想着自己也弄一个仿制品来玩玩吧。

    准备工作

    先研究一下Github默认头像的结构,先拿几张Github用户的默认头像来看看:

    github_user_avatar_1
    github_user_avatar_2

    先查看一下这些图片的大小,为 420*420px,仔细看一下,结构应该是这样的:

    • 中心矩阵为 5x5
    • 每一块长度为 70px
    • 边缘的灰色条条长度为 35px

    搞清楚这些,就可以开始自己撸了,决定使用 Java + OpenCV 3.4 来制作图像。

    代码

    你可以看下面的代码,也可以在Github上查看代码:FlyAndNotDown-GithubAvatarGenerator

    GithubAvatarGenerator.java

    import org.opencv.core.CvType;
    import org.opencv.core.Mat;
    import org.opencv.imgcodecs.Imgcodecs;
    
    import java.util.Random;
    
    /**
     * Github头像生成器
     */
    public class GithubAvatarGenerator {
        private static final int GITHUB_AVATAR_ROWS = 420;
        private static final int GITHUB_AVATAR_COLS = 420;
        // 围边使用的灰色
        private static final int [] COLOR_GREY_BGR = new int[] {
                230, 230, 230
        };
        // 选出一些大概会比较好看的颜色池用于生成
        private static final int [][] COLOR_POOL_RGB = new int[][] {
                {170, 205, 102},
                {159, 255, 84},
                {209, 206, 0},
                {255, 255, 0},
                {47, 107, 85},
                {47, 255, 173},
                {0, 173, 205},
                {8, 101, 139},
                {180, 180, 238},
                {106, 106, 255},
                {155, 211, 255},
                {204, 50, 153},
                {101, 119, 139}
        };
        // 外围宽度
        private static final int GITHUB_AVATAR_FRAME_WIDTH = 35;
        // Block宽度
        private static final int GITHUB_AVATAR_BLOCK_WIDTH = 70;
        // Vertex 大小
        private static final int GITHUB_AVATAR_VERTEX_WIDTH = 5;
    
        /**
         * 获取一个 5x5 的随机填充对称矩阵
         * @return 5x5 随机填充对称矩阵
         */
        private boolean [][] getGithubAvatarVertex() {
            // 新建矩阵
            boolean [][] vertex = new boolean[5][5];
    
            // 先随机填充中间一条
            Random random = new Random();
            for (int i = 0; i < 5; i++) {
                if (random.nextBoolean()) {
                    vertex[i][2] = true;
                }
            }
    
            // 随机填充半边
            for (int i = 0; i < 5; i++) {
                for (int j = 0; j < 2; j++) {
                    if (random.nextBoolean()) {
                        vertex[i][j] = true;
                    }
                }
            }
    
            // 将填充的半边对称复制到另外半边
            for (int i = 0; i < 5; i++) {
                for (int j = 3; j < 5; j++) {
                    vertex[i][j] = vertex[i][4 - j];
                }
            }
    
            return vertex;
        }
    
        /**
         * 获取一个随机的 github 头像 BGR 信息
         * @return 图像 BGR 信息
         */
        private byte [][][] getGithubAvatarRGBData() {
            // 通道
            int channels = 3;
    
            // BGR 信息
            byte [][][] bgrData = new byte[GITHUB_AVATAR_ROWS][GITHUB_AVATAR_COLS][channels];
    
            // 获取一个随机的颜色索引
            Random random = new Random();
            int randomIndex = random.nextInt() % COLOR_POOL_RGB.length;
            if (randomIndex < 0) {
                randomIndex = 0 - randomIndex;
            }
            // 用索引获取一个随机的颜色
            int [] randomBGR = new int[3];
            System.arraycopy(COLOR_POOL_RGB[randomIndex], 0, randomBGR, 0, 3);
    
            // 先将外围一圈 35px 填充成灰色
            // top
            for (int i = 0; i < GITHUB_AVATAR_FRAME_WIDTH; i++) {
                for (int j = 0; j < GITHUB_AVATAR_COLS; j++) {
                    for (int k = 0; k < channels; k++) {
                        bgrData[i][j][k] = (byte) COLOR_GREY_BGR[k];
                    }
                }
            }
            // bottom
            for (int i = GITHUB_AVATAR_COLS - 1; i > GITHUB_AVATAR_COLS - GITHUB_AVATAR_FRAME_WIDTH - 1; i--) {
                for (int j = 0; j < GITHUB_AVATAR_COLS; j++) {
                    for (int k = 0; k < channels; k++) {
                        bgrData[i][j][k] = (byte) COLOR_GREY_BGR[k];
                    }
                }
            }
            // left
            for (int i = 0; i < GITHUB_AVATAR_COLS; i++) {
                for (int j = 0; j <GITHUB_AVATAR_FRAME_WIDTH; j++) {
                    for (int k = 0; k < channels; k++) {
                        bgrData[i][j][k] = (byte) COLOR_GREY_BGR[k];
                    }
                }
            }
            // right
            for (int i = 0; i < GITHUB_AVATAR_COLS; i++) {
                for (int j = GITHUB_AVATAR_ROWS - 1; j > GITHUB_AVATAR_ROWS - GITHUB_AVATAR_FRAME_WIDTH - 1; j--) {
                    for (int k = 0; k < channels; k++) {
                        bgrData[i][j][k] = (byte) COLOR_GREY_BGR[k];
                    }
                }
            }
            // 将中间 5x5 的范围按照矩阵信息填充
            boolean [][] vertex = getGithubAvatarVertex();
            for (int i = 0; i < GITHUB_AVATAR_VERTEX_WIDTH; i++) {
                for (int j = 0; j < GITHUB_AVATAR_VERTEX_WIDTH; j++) {
                    if (vertex[i][j]) {
                        for (int m = GITHUB_AVATAR_FRAME_WIDTH + i * GITHUB_AVATAR_BLOCK_WIDTH;
                             m < GITHUB_AVATAR_FRAME_WIDTH + i * GITHUB_AVATAR_BLOCK_WIDTH + GITHUB_AVATAR_BLOCK_WIDTH;
                             m++) {
                            for (int n = GITHUB_AVATAR_FRAME_WIDTH + j * GITHUB_AVATAR_BLOCK_WIDTH;
                                 n < GITHUB_AVATAR_FRAME_WIDTH + j * GITHUB_AVATAR_BLOCK_WIDTH + GITHUB_AVATAR_BLOCK_WIDTH;
                                 n++) {
                                for (int k = 0; k < channels; k++) {
                                    bgrData[m][n][k] = (byte) randomBGR[k];
                                }
                            }
                        }
                    } else {
                        for (int m = GITHUB_AVATAR_FRAME_WIDTH + i * GITHUB_AVATAR_BLOCK_WIDTH;
                             m < GITHUB_AVATAR_FRAME_WIDTH + i * GITHUB_AVATAR_BLOCK_WIDTH + GITHUB_AVATAR_BLOCK_WIDTH;
                             m++) {
                            for (int n = GITHUB_AVATAR_FRAME_WIDTH + j * GITHUB_AVATAR_BLOCK_WIDTH;
                                 n < GITHUB_AVATAR_FRAME_WIDTH + j * GITHUB_AVATAR_BLOCK_WIDTH + GITHUB_AVATAR_BLOCK_WIDTH;
                                 n++) {
                                for (int k = 0; k < channels; k++) {
                                    bgrData[m][n][k] = (byte) COLOR_GREY_BGR[k];
                                }
                            }
                        }
                    }
                }
            }
    
            // 返回 BGR 信息
            return bgrData;
        }
    
        /**
         * 获取一个随机的头像
         * @param fileName 文件名
         */
        public void getARandomAvatar(String fileName) {
            // 新建一个 img 文件
            Mat img = new Mat(
                    GITHUB_AVATAR_ROWS,
                    GITHUB_AVATAR_COLS,
                    // RGB 通道
                    CvType.CV_8UC3
            );
    
            // 长
            int width = img.cols();
            // 宽
            int height = img.height();
            // 通道
            int channels = img.channels();
    
            // 图像中所有像素加通道的储存数据
            int [][][] data = new int[height][width][channels];
    
            // 获取数据头像 BGR 信息
            byte [][][] randomAvatarBGR = getGithubAvatarRGBData();
    
            // 将生成的 github 头像信息复制到图片中
            for (int i = 0; i < height; i++) {
                for (int j = 0; j < width; j++) {
                    img.put(i, j, randomAvatarBGR[i][j]);
                }
            }
    
            // 保存图片
            Imgcodecs.imwrite(fileName, img);
        }
    }
    

    Main.java

    import org.opencv.core.Core;
    
    public class Main {
        static {
            System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
        }
    
        // main
        public static void main(String[] args) {
            GithubAvatarGenerator githubAvatarGenerator = new GithubAvatarGenerator();
            for (int i = 1; i <= 20; i ++) {
                githubAvatarGenerator.getARandomAvatar(String.valueOf(i) + ".jpg");
            }
        }
    }
    

    效果

    一次性产生20张图片,我们来看看其中几张的效果


    result_avatar_1
    result_avatar_2
    result_avatar_3
    result_avatar_4
    result_avatar_5
    result_avatar_6

    挺萌的蛤!

    相关文章

      网友评论

        本文标题:用Java和OpenCV生成Github默认头像

        本文链接:https://www.haomeiwen.com/subject/ivwqxftx.html