Code Monkey home page Code Monkey logo

yolox-tf2's Introduction

YOLOX:You Only Look Once目标检测模型在Tensorflow2当中的实现


目录

  1. 仓库更新 Top News
  2. 相关仓库 Related code
  3. 性能情况 Performance
  4. 实现的内容 Achievement
  5. 所需环境 Environment
  6. 文件下载 Download
  7. 训练步骤 How2train
  8. 预测步骤 How2predict
  9. 评估步骤 How2eval
  10. 参考资料 Reference

Top News

2022-04:支持多GPU训练,新增各个种类目标数量计算,新增heatmap。

2022-03:进行了大幅度的更新,支持step、cos学习率下降法、支持adam、sgd优化器选择、支持学习率根据batch_size自适应调整、新增图片裁剪。
BiliBili视频中的原仓库地址为:https://github.com/bubbliiiing/yolox-tf2/tree/bilibili

2021-10:创建仓库,支持不同尺寸模型训练、支持大量可调整参数,支持fps、视频预测、批量预测等功能。  

相关仓库

模型 路径
YoloV3 https://github.com/bubbliiiing/yolo3-tf2
Efficientnet-Yolo3 https://github.com/bubbliiiing/efficientnet-yolo3-tf2
YoloV4 https://github.com/bubbliiiing/yolov4-tf2
YoloV4-tiny https://github.com/bubbliiiing/yolov4-tiny-tf2
Mobilenet-Yolov4 https://github.com/bubbliiiing/mobilenet-yolov4-tf2
YoloV5-V5.0 https://github.com/bubbliiiing/yolov5-tf2
YoloV5-V6.1 https://github.com/bubbliiiing/yolov5-v6.1-tf2
YoloX https://github.com/bubbliiiing/yolox-tf2
Yolov7 https://github.com/bubbliiiing/yolov7-tf2
Yolov7-tiny https://github.com/bubbliiiing/yolov7-tiny-tf2

性能情况

训练数据集 权值文件名称 测试数据集 输入图片大小 mAP 0.5:0.95 mAP 0.5
COCO-Train2017 yolox_tiny.h5 COCO-Val2017 640x640 34.7 53.6
COCO-Train2017 yolox_s.h5 COCO-Val2017 640x640 39.2 58.7
COCO-Train2017 yolox_m.h5 COCO-Val2017 640x640 46.1 65.2
COCO-Train2017 yolox_l.h5 COCO-Val2017 640x640 49.3 68.1
COCO-Train2017 yolox_x.h5 COCO-Val2017 640x640 50.5 69.2

实现的内容

  • 主干特征提取网络:使用了Focus网络结构。
  • 分类回归层:Decoupled Head,在YoloX中,Yolo Head被分为了分类回归两部分,最后预测的时候才整合在一起。
  • 训练用到的小技巧:Mosaic数据增强、CIOU(原版是IOU和GIOU,CIOU效果类似,都是IOU系列的,甚至更新一些)、学习率余弦退火衰减。
  • Anchor Free:不使用先验框
  • SimOTA:为不同大小的目标动态匹配正样本。

所需环境

tensorflow-gpu==2.2.0

文件下载

训练所需的权值可在百度网盘中下载。
链接: https://pan.baidu.com/s/1t6wgcSP85do1Y4lqVCVDMw
提取码: m25d

VOC数据集下载地址如下,里面已经包括了训练集、测试集、验证集(与测试集一样),无需再次划分:
链接: https://pan.baidu.com/s/1YuBbBKxm2FGgTU5OfaeC5A
提取码: uack

训练步骤

a、训练VOC07+12数据集

  1. 数据集的准备
    本文使用VOC格式进行训练,训练前需要下载好VOC07+12的数据集,解压后放在根目录

  2. 数据集的处理
    修改voc_annotation.py里面的annotation_mode=2,运行voc_annotation.py生成根目录下的2007_train.txt和2007_val.txt。

  3. 开始网络训练
    train.py的默认参数用于训练VOC数据集,直接运行train.py即可开始训练。

  4. 训练结果预测
    训练结果预测需要用到两个文件,分别是yolo.py和predict.py。我们首先需要去yolo.py里面修改model_path以及classes_path,这两个参数必须要修改。
    model_path指向训练好的权值文件,在logs文件夹里。
    classes_path指向检测类别所对应的txt。

    完成修改后就可以运行predict.py进行检测了。运行后输入图片路径即可检测。

b、训练自己的数据集

  1. 数据集的准备
    本文使用VOC格式进行训练,训练前需要自己制作好数据集,
    训练前将标签文件放在VOCdevkit文件夹下的VOC2007文件夹下的Annotation中。
    训练前将图片文件放在VOCdevkit文件夹下的VOC2007文件夹下的JPEGImages中。

  2. 数据集的处理
    在完成数据集的摆放之后,我们需要利用voc_annotation.py获得训练用的2007_train.txt和2007_val.txt。
    修改voc_annotation.py里面的参数。第一次训练可以仅修改classes_path,classes_path用于指向检测类别所对应的txt。
    训练自己的数据集时,可以自己建立一个cls_classes.txt,里面写自己所需要区分的类别。
    model_data/cls_classes.txt文件内容为:

cat
dog
...

修改voc_annotation.py中的classes_path,使其对应cls_classes.txt,并运行voc_annotation.py。

  1. 开始网络训练
    训练的参数较多,均在train.py中,大家可以在下载库后仔细看注释,其中最重要的部分依然是train.py里的classes_path。
    classes_path用于指向检测类别所对应的txt,这个txt和voc_annotation.py里面的txt一样!训练自己的数据集必须要修改!
    修改完classes_path后就可以运行train.py开始训练了,在训练多个epoch后,权值会生成在logs文件夹中。

  2. 训练结果预测
    训练结果预测需要用到两个文件,分别是yolo.py和predict.py。在yolo.py里面修改model_path以及classes_path。
    model_path指向训练好的权值文件,在logs文件夹里。
    classes_path指向检测类别所对应的txt。

    完成修改后就可以运行predict.py进行检测了。运行后输入图片路径即可检测。

预测步骤

a、使用预训练权重

  1. 下载完库后解压,在百度网盘下载yolo_weights.pth,放入model_data,运行predict.py,输入
img/street.jpg
  1. 在predict.py里面进行设置可以进行fps测试和video视频检测。

b、使用自己训练的权重

  1. 按照训练步骤训练。
  2. 在yolo.py文件里面,在如下部分修改model_path和classes_path使其对应训练好的文件;model_path对应logs文件夹下面的权值文件,classes_path是model_path对应分的类
_defaults = {
    #--------------------------------------------------------------------------#
    #   使用自己训练好的模型进行预测一定要修改model_path和classes_path!
    #   model_path指向logs文件夹下的权值文件,classes_path指向model_data下的txt
    #   如果出现shape不匹配,同时要注意训练时的model_path和classes_path参数的修改
    #--------------------------------------------------------------------------#
    "model_path"        : 'model_data/yolox_s.h5',
    "classes_path"      : 'model_data/coco_classes.txt',
    #---------------------------------------------------------------------#
    #   输入图片的大小,必须为32的倍数。
    #---------------------------------------------------------------------#
    "input_shape"       : [640, 640],
    #---------------------------------------------------------------------#
    #   所使用的YoloX的版本。s、m、l、x
    #---------------------------------------------------------------------#
    "phi"               : 's',
    #---------------------------------------------------------------------#
    #   只有得分大于置信度的预测框会被保留下来
    #---------------------------------------------------------------------#
    "confidence"        : 0.5,
    #---------------------------------------------------------------------#
    #   非极大抑制所用到的nms_iou大小
    #---------------------------------------------------------------------#
    "nms_iou"           : 0.3,
    #---------------------------------------------------------------------#
    #   最多预测框的数量
    #---------------------------------------------------------------------#
    "max_boxes"         : 100,
    #---------------------------------------------------------------------#
    #   该变量用于控制是否使用letterbox_image对输入图像进行不失真的resize,
    #   在多次测试后,发现关闭letterbox_image直接resize的效果更好
    #---------------------------------------------------------------------#
    "letterbox_image"   : True,
}
  1. 运行predict.py,输入
img/street.jpg
  1. 在predict.py里面进行设置可以进行fps测试和video视频检测。

评估步骤

a、评估VOC07+12的测试集

  1. 本文使用VOC格式进行评估。VOC07+12已经划分好了测试集,无需利用voc_annotation.py生成ImageSets文件夹下的txt。
  2. 在yolo.py里面修改model_path以及classes_path。model_path指向训练好的权值文件,在logs文件夹里。classes_path指向检测类别所对应的txt。
  3. 运行get_map.py即可获得评估结果,评估结果会保存在map_out文件夹中。

b、评估自己的数据集

  1. 本文使用VOC格式进行评估。
  2. 如果在训练前已经运行过voc_annotation.py文件,代码会自动将数据集划分成训练集、验证集和测试集。如果想要修改测试集的比例,可以修改voc_annotation.py文件下的trainval_percent。trainval_percent用于指定(训练集+验证集)与测试集的比例,默认情况下 (训练集+验证集):测试集 = 9:1。train_percent用于指定(训练集+验证集)中训练集与验证集的比例,默认情况下 训练集:验证集 = 9:1。
  3. 利用voc_annotation.py划分测试集后,前往get_map.py文件修改classes_path,classes_path用于指向检测类别所对应的txt,这个txt和训练时的txt一样。评估自己的数据集必须要修改。
  4. 在yolo.py里面修改model_path以及classes_path。model_path指向训练好的权值文件,在logs文件夹里。classes_path指向检测类别所对应的txt。
  5. 运行get_map.py即可获得评估结果,评估结果会保存在map_out文件夹中。

Reference

https://github.com/Megvii-BaseDetection/YOLOX

yolox-tf2's People

Contributors

bubbliiiing avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

yolox-tf2's Issues

About download link

Thank you for sharing code.

I want to download voc files but can't use it.
Could you upload files through google drive?
Or let me know the annotation format of txt file. (ex : 009961.jpg 500 374 dog 69 4 392 345) (Just one line)

mAP回调问题

upup,我把您的代码修改了一下,从以前每个epoch结束后计算验证集的mAP改成了计算测试集的mAP。发现从回调中计算的mAP(0.75)和通过get_map文件计算mAP(0.75)是不同的。我看回调中是第338epoch中取得的mAP(0.75)最大值为98.69%,于是我找到第338epoch的权重计算了一下mAP(0.75),但是值为96.92。我的数据集中没有difficult,不知道为什么会出现这种情况,您看看是我代码哪里有问题吗?我在代码的以下几个位置进行了修改
8IF0X_$RIY@){97XXPBS(L](https://user-images.githubusercontent.com/94728846/170474596-5f47b999-6884-4b4d-8cb2-5f6c327442b8.png) ![H)P59(6N@XIY086Z1V%FOG
8@~A%0@CQ46J_F }1I E4
HT@Z8FHF5BGT8RIO 398U
NOJN85~QG(P BQ@}$S(88)F

mAP相关问题

upup刚看了您的新代码。 您在mAP验证的过程中,为了训练速度好像和平常计算mAP时用的参数不同,请问该怎么调成和平常计算mAP一样的计算方式呢?​

是不是30系列的显卡不兼容问题

哥,你使用的显卡是30系列的吗? 30系列显卡有时候,会出现tensorflow2.x中有函数调用问题还有就是python环境版本的问题
都讲不好 (哭笑)

批量计算mAP

请问一下up该怎么批量计算mAP啊,目前用的是固定epoch次数计算mAP感觉随机性比较大。

损失函数

你好 ,想问下官方的yolox里关闭mosaic后在计算损失时会加入l1loss,在tf2这版本的代码里是不是没有实现呢?您是否是试过加入l1 loss,对结果有影响吗?

自定义SiLU不支持保存模型重新加载

up你好,如果保存模型参数和结构然后重新load的话,其中SiLU和Focus层是不支持的,因为它们不是tf2预定义的层类,先请问下SiLU函数可不可以通过在模型静态图定义的过程中,更改为tf.nn.silu(),因为不太熟悉tf2,所以希望up能提供关于一些修改silu的思路,Focus层已经解决了,不胜感激

权重问题

老师请问您有voc数据集训练的权重嘛

查看模型参数量的问题

想用summary(YoloBody(20,'s'), input_size=(640, 640,3))查看模型参数量,结果报错;
显示的是在focus块里 x = torch.cat((patch_top_left, patch_bot_left, patch_top_right, patch_bot_right,), dim=1,)
RuntimeError: Sizes of tensors must match except in dimension 1. Expected size 2 but got size 1 for tensor number 2 in the list.

upup,关于网络修改我想请问你一个问题。

东西有点长,麻烦up耐心看一下,感谢!!

def loop_body(b, num_fg, loss_iou, loss_obj, loss_cls, loss_force, loss_angle):
        num_gt  = tf.cast(nlabel[b], tf.int32)
        gt_bboxes_per_image     = labels[b][:num_gt, :4]        # 每张图片的真实框
        gt_dis                  = labels[b][:num_gt,  4]        # 每张图片的真实距离,主要加的这里
        gt_classes              = labels[b][:num_gt,  5]        # 每张图片的真实类别
        bboxes_preds_per_image  = bbox_preds[b]                 # 每张图片的预测框
        obj_preds_per_image     = obj_preds[b]                  # 每张图片的置信度
        dis_preds_per_image     = force_preds[b]                # 每张图片的预测距离
        cls_preds_per_image     = cls_preds[b]                  # 每张图片的预测类别

        def f1():
            num_fg_img    = tf.cast(tf.constant(0), K.dtype(outputs))
            cls_target    = tf.cast(tf.zeros((0, num_classes)), K.dtype(outputs))
            reg_target    = tf.cast(tf.zeros((0, 4)), K.dtype(outputs))
            obj_target    = tf.cast(tf.zeros((total_num_anchors, 1)), K.dtype(outputs))
            dis_target    = tf.cast(tf.zeros((0, 1)), K.dtype(outputs))           # 主要加的这里
            fg_mask       = tf.cast(tf.zeros(total_num_anchors), tf.bool)
            return num_fg_img, cls_target, reg_target, obj_target, force_target, fg_mask

        def f2():
            gt_matched_classes, fg_mask, pred_ious_this_matching, matched_gt_inds, num_fg_img = get_assignments( 
                gt_bboxes_per_image, gt_classes, bboxes_preds_per_image, obj_preds_per_image, cls_preds_per_image,
                x_shifts, y_shifts, expanded_strides, num_classes, num_gt, total_num_anchors
            )
            reg_target  = tf.cast(tf.gather_nd(gt_bboxes_per_image, tf.reshape(matched_gt_inds, [-1, 1])), K.dtype(outputs))
            cls_target  = tf.cast(tf.one_hot(tf.cast(gt_matched_classes, tf.int32), num_classes) * tf.expand_dims(pred_ious_this_matching, -1), K.dtype(outputs))
            obj_target  = tf.cast(tf.expand_dims(fg_mask, -1), K.dtype(outputs))
            gt_matched_dis = tf.gather_nd(gt_dis, tf.reshape(matched_gt_inds, [-1, 1]))    # 主要加的这里
            dis_target  = tf.cast(tf.expand_dims(tf.cast(gt_matched_dis, tf.float32), -1), K.dtype(outputs))      
            # 这里是我增加的距离信息,把tf.float32改成tf.int32就跑通了
            return num_fg_img, cls_target, reg_target, obj_target, force_target, fg_mask

        num_fg_img, cls_target, reg_target, obj_target, force_target, angle_target, fg_mask = tf.cond(tf.equal(num_gt, 0), f1, f2)
        num_fg      += num_fg_img
        loss_iou    += K.sum(1 - box_ciou(reg_target, tf.boolean_mask(bboxes_preds_per_image, fg_mask)))
        loss_obj    += K.sum(K.binary_crossentropy(obj_target, obj_preds_per_image, from_logits=True))
        loss_cls    += K.sum(K.binary_crossentropy(cls_target, tf.boolean_mask(cls_preds_per_image, fg_mask), from_logits=True))
        loss_dis  += K.sum(tf.losses.mean_squared_error(dis_target, tf.boolean_mask(dis_preds_per_image, fg_mask)))               # 主要加的这里
        return b + 1, num_fg, loss_iou, loss_obj, loss_cls, loss_dis

    _, num_fg, loss_iou, loss_obj, loss_cls, loss_dis = tf.while_loop(lambda b,*args: b < tf.cast(tf.shape(outputs)[0], tf.int32), loop_body, [0, num_fg, loss_iou, loss_obj, loss_cls, loss_dis])
    
    num_fg      = tf.cast(tf.maximum(num_fg, 1), K.dtype(outputs))
    reg_weight  = 5.0
    loss        = reg_weight * loss_iou + loss_obj + loss_cls + loss_dis
    return loss / num_fg

针对你的源码我想加入距离的预测,代码如上,然而在yolo_training的get_losses函数中tf.cond出现这样的报错

TypeError: true_fn and false_fn arguments to tf.cond must have the same number, type, and overall structure of return values.

    true_fn output: [None, None, None, None, None, <tf.Tensor 'gradient_tape/model_1/yolo_loss/while/gradients/model_1/yolo_loss/while/cond_grad/zeros_like:0' shape=(None, None) dtype=float32>, <tf.Tensor 'gradient_tape/model_1/yolo_loss/while/gradients/model_1/yolo_loss/while/cond_grad/zeros_like_1:0' shape=(None, None) dtype=float32>, <tf.Tensor 'gradient_tape/model_1/yolo_loss/while/gradients/model_1/yolo_loss/while/cond_grad/zeros_like_2:0' shape=(None, None) dtype=float32>, <tf.Tensor 'gradient_tape/model_1/yolo_loss/while/gradients/model_1/yolo_loss/while/cond_grad/zeros_like_3:0' shape=(None, None) dtype=float32>, None, <tensorflow.python.framework.indexed_slices.IndexedSlices object at 0x000001FD7DA1A7F0>]
    false_fn output: [None, None, None, None, None, <tf.Tensor 'gradient_tape/model_1/yolo_loss/while/gradients/model_1/yolo_loss/while/cond_grad/Identity:0' shape=(None, None) dtype=float32>, <tf.Tensor 'gradient_tape/model_1/yolo_loss/while/gradients/model_1/yolo_loss/while/cond_grad/Identity_1:0' shape=(None, None) dtype=float32>, <tf.Tensor 'gradient_tape/model_1/yolo_loss/while/gradients/model_1/yolo_loss/while/cond_grad/Identity_2:0' shape=(None, None) dtype=float32>, <tf.Tensor 'gradient_tape/model_1/yolo_loss/while/gradients/model_1/yolo_loss/while/cond_grad/Identity_3:0' shape=(None, None) dtype=float32>, None, <tensorflow.python.framework.indexed_slices.IndexedSlices object at 0x000001FD7DA1A880>]

    Error details:
    The two structures don't have the same nested structure.

    First structure: type=list str=[None, None, None, None, None, <tf.Tensor 'gradient_tape/model_1/yolo_loss/while/gradients/model_1/yolo_loss/while/cond_grad/zeros_like:0' shape=(None, None) dtype=float32>, <tf.Tensor 'gradient_tape/model_1/yolo_loss/while/gradients/model_1/yolo_loss/while/cond_grad/zeros_like_1:0' shape=(None, None) dtype=float32>, <tf.Tensor 'gradient_tape/model_1/yolo_loss/while/gradients/model_1/yolo_loss/while/cond_grad/zeros_like_2:0' shape=(None, None) dtype=float32>, <tf.Tensor 'gradient_tape/model_1/yolo_loss/while/gradients/model_1/yolo_loss/while/cond_grad/zeros_like_3:0' shape=(None, None) dtype=float32>, None, <tensorflow.python.framework.indexed_slices.IndexedSlices object at 0x000001FD7DA1A7F0>]

    Second structure: type=list str=[None, None, None, None, None, <tf.Tensor 'gradient_tape/model_1/yolo_loss/while/gradients/model_1/yolo_loss/while/cond_grad/Identity:0' shape=(None, None) dtype=float32>, <tf.Tensor 'gradient_tape/model_1/yolo_loss/while/gradients/model_1/yolo_loss/while/cond_grad/Identity_1:0' shape=(None, None) dtype=float32>, <tf.Tensor 'gradient_tape/model_1/yolo_loss/while/gradients/model_1/yolo_loss/while/cond_grad/Identity_2:0' shape=(None, None) dtype=float32>, <tf.Tensor 'gradient_tape/model_1/yolo_loss/while/gradients/model_1/yolo_loss/while/cond_grad/Identity_3:0' shape=(None, None) dtype=float32>, None, <tensorflow.python.framework.indexed_slices.IndexedSlices object at
0x000001FD7DA1A880>]

    More specifically: Incompatible CompositeTensor TypeSpecs: type=IndexedSlicesSpec str=IndexedSlicesSpec(TensorShape([None]), tf.float32, tf.int64, tf.int32, TensorShape([None])) vs. type=IndexedSlicesSpec str=IndexedSlicesSpec(TensorShape([None]), tf.float32, tf.int64, tf.int64, TensorShape([None]))
    Entire first structure:
    [., ., ., ., ., ., ., ., ., ., .]
    Entire second structure:
    [., ., ., ., ., ., ., ., ., ., .]

但是在f2()函数中把tf.float32改成tf.int32代码就能跑通了(不过我距离信息不太能是int😂),所以想询问一下您这是怎么回事,而且怎样才能换成float形式。感谢赐教!!!

dis_target  = tf.cast(tf.expand_dims(tf.cast(gt_matched_dis, tf.int32), -1), K.dtype(outputs))      # 这里是我增加的距离信息

关于我亲测up框架提出的一些建议(性能与速度篇)

首先我拿代码过来,马上就对比了一下官方yolo与up这个,官方的是0.022-0.035 推理速度把 这里记住了是35毫秒哦,然后我拿了up代码亲测速度是0.22-0.35 也就是220毫秒 相差太大了,随后我发现up用的是PIL这个库 这个库确实是拖慢了检测速度啊,建议使用cv2 库去对图片进行处理可以提高很快的速度。

Intel MKL ERROR: Parameter 6 was incorrect on entry to DGELSD.

Intel MKL ERROR: Parameter 6 was incorrect on entry to DGELSD.
RuntimeWarning: invalid value encountered in less
UP这种报错是什么原因呢,只要一报错,后续每次迭代的mAP都无法计算出来了,提示不能检测到目标。

回复

我的是3080,这个问题是我上个问题引过来的,搞不明白 (苦笑

train.py也报错

哥,在s版本的时候,train.py在运行的时候总是在第4个epoch突然中断,
tensorflow.python.framework.errors_impl.InvalidArgumentError: Incompatible shapes: [8400,5] vs. [0,5]
[[{{node model_1/yolo_loss/while/body/_1/model_1/yolo_loss/while/logistic_loss_1/mul}}]] [Op:__inference_test_function_37457]

Function call stack:
test_function

2021-11-18 20:07:59.290423: W tensorflow/core/kernels/data/generator_dataset_op.cc:107] Error occurred when finalizing GeneratorDataset iterator: Failed precondition: Python interpreter state is not initialized. The process may be terminated.
[[{{node PyFunc}}]]

但是GPU还在被调用

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.