GithubHelp home page GithubHelp logo

dfd-tud / deda Goto Github PK

View Code? Open in Web Editor NEW
1.5K 46.0 92.0 2 MB

Home Page: https://dfd.inf.tu-dresden.de

License: GNU General Public License v3.0

Python 60.06% HTML 25.09% CSS 1.50% JavaScript 13.35%
yellow-dots tracking-dots printer-forensic

deda's Introduction

DEDA - tracking Dots Extraction, Decoding and Anonymisation toolkit

Document Colour Tracking Dots, or yellow dots, are small systematic dots which encode information about the printer and/or the printout itself. This process is integrated in almost every commercial colour laser printer. This means that almost every printout contains coded information about the source device, such as the serial number.

On the one hand, this tool gives the possibility to read out and decode these forensic features and on the other hand, it allows anonymisation to prevent arbitrary tracking.

If you use this software, please cite the paper: Timo Richter, Stephan Escher, Dagmar Schönfeld, and Thorsten Strufe. 2018. Forensic Analysis and Anonymisation of Printed Documents. In Proceedings of the 6th ACM Workshop on Information Hiding and Multimedia Security (IH&MMSec '18). ACM, New York, NY, USA, 127-138. DOI: https://doi.org/10.1145/3206004.3206019


Installation

  • Install Python 3
  • Install Deda

From PyPI: $ pip3 install --user deda

Or from current directory: $ pip3 install --user .

  • Optional requirement by deda_anonmask_apply (Unix and GNU/Linux only): $ pip3 install --user wand

Without Wand, pages containing white areas on images cannot be anonymised.


Graphical User Interface

  • To open the GUI type: $ deda_gui

Terminal Application

1. Reading tracking data

Tracking data can be read and sometimes be decoded from a scanned image. For good results the input shall use a lossless compression (e.g. png) and 300 dpi. Make sure to set a neutral contrast $ deda_parse_print INPUTFILE

2. Find a divergent printer in a set of scanned documents

$ deda_compare_prints INPUT1 INPUT2 [INPUT3] ...

3. Analysing an unknown tracking pattern

New patterns might not be recognised by parse_print. The dots can be extracted for further analysis.
$ deda_extract_yd INPUTFILE

4. Create your own tracking dots

If you want to create your own tracking dots matrix and add it to a pdf document, pass the contents as parameters (see deda_create_dots -h). $ deda_create_dots PDFINPUT

The calibration page ($ deda_anonmask_create -w) may be used as an input.

5. Anonymise a scanned image

This (mostly) removes tracking data from a scan:
$ deda_clean_document INPUTFILE OUTPUTFILE

6. Anonymise a document for printing
  • Save your document as a PDF file and call it DOCUMENT.PDF.

  • Print the testpage.pdf file created by
    $ deda_anonmask_create -w
    without any page margin.

  • Scan the document (300 dpi) and pass the lossless file to
    $ deda_anonmask_create -r INPUTFILE
    This creates 'mask.json', the individual printer's anonymisation mask.

  • Now apply the anonymisation mask:
    $ deda_anonmask_apply mask.json DOCUMENT.PDF This creates 'masked.pdf', the anonymised document. It may be printed with a zero page margin setting.

Check whether a masked page covers your printer's tracking dots by using a microscope. The mask's dot radius, x and y offsets can be customised and passed to deda_anonmask_apply as parameters.

Note that if DOCUMENT.PDF contains graphics with white or light coloured parts, these can only be masked if "wand" is installed (see above).


Troubleshooting

deda_parse_print: command not found

Possible solutions:

  • Install deda accordig to chapter 0
  • Execute $ export PATH="$PATH:$(python -c 'import site,os; print(os.path.join(site.USER_BASE, "bin"))')"
Deda does not recognise my tracking dots

Set up your scan program so that it does not eliminate the paper structure nor tracking dots by some threshold and check again. Remember that monochrome pages as well as inkjet prints might not contain tracking dots.

My printer does not print tracking dots. Can I hide this fact?

If there are really no tracking dots, you can either create your own ones (deda_create_dots) or print the calibration page (deda_anonmask_create -w) with another printer and use the mask for your own printer. You can use the anonymised version of the tracking dots or just copy them (deda_anonmask_create --copy). See chapters "Anonymise a document for printing" and "Create your own tracking dots".

Install Error: command 'x86_64-linux-gnu-gcc' failed with exit status 1

This may be caused by the eel dependency which is needed for the GUI. Try $ sudo apt-get install build-essential autoconf libtool pkg-config python3.6-dev gcc && pip3 install --user eel

wand.exceptions.PolicyError: attempt to perform an operation not allowed by the security policy PDF' @ error/constitute.c/IsCoderAuthorized/408

This is being caused by ImageMagick. Either remove Wand (pip3 uninstall wand) or add <policy domain="coder" rights="read | write" pattern="PDF" /> just before </policymap> in /etc/ImageMagick-*/policy.xml. See also https://stackoverflow.com/questions/52998331/imagemagick-security-policy-pdf-blocking-conversion.

deda's People

Contributors

alvv-z avatar dfd-tud avatar dogtopus avatar melongbob avatar noraj avatar timojuez 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  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  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

deda's Issues

OpenCV false build path?

I'm wondering whether there is a false build path included in deda or whether it's just not correctly set up on my computer.
The call path is strange because there is no user "travis" on my computer, thus, I am wondering whether this is something that is hard-coded.

python3 deda_parse_print.py new_dots.pdf
OpenCV(3.4.1) Error: Assertion failed (!buf.empty() && buf.isContinuous()) in imdecode_, file /Users/travis/build/skvark/opencv-python/opencv/modules/imgcodecs/src/loadsave.cpp, line 731

Any idea?

Sample images?

Would it be possible to provide some sample images so we can test whether it detection etc works nicely?

Is it possible to use this with standard US Letter sized paper?

I want to anonymise a document for printing. However, I noticed the testpage.pdf is using the A4/ISO 216 paper size. If I try to print it, it will be printed at a reduced size because it is a different aspect ratio. Is it possible to use this program with standard US Letter sized paper?

ImportError: cannot import name 'pdf' from 'PyPDF2'

wesjo@ubuntu:~$ deda_gui
/home/wesjo/.local/lib/python3.8/site-packages/numpy/core/getlimits.py:500: UserWarning: The value of the smallest subnormal for <class 'numpy.float64'> type is zero.
  setattr(self, word, getattr(machar, word).flat[0])
/home/wesjo/.local/lib/python3.8/site-packages/numpy/core/getlimits.py:89: UserWarning: The value of the smallest subnormal for <class 'numpy.float64'> type is zero.
  return self._float_to_str(self.smallest_subnormal)
/home/wesjo/.local/lib/python3.8/site-packages/numpy/core/getlimits.py:500: UserWarning: The value of the smallest subnormal for <class 'numpy.float32'> type is zero.
  setattr(self, word, getattr(machar, word).flat[0])
/home/wesjo/.local/lib/python3.8/site-packages/numpy/core/getlimits.py:89: UserWarning: The value of the smallest subnormal for <class 'numpy.float32'> type is zero.
  return self._float_to_str(self.smallest_subnormal)
Traceback (most recent call last):
  File "/home/wesjo/.local/bin/deda_gui", line 5, in <module>
    from deda_gui.deda_gui import main
  File "/home/wesjo/.local/lib/python3.8/site-packages/deda_gui/deda_gui.py", line 18, in <module>
    from libdeda.pattern_handler import TDM, Pattern4
  File "/home/wesjo/.local/lib/python3.8/site-packages/libdeda/__init__.py", line 1, in <module>
    from . import print_parser, privacy, extract_yd, pattern_handler
  File "/home/wesjo/.local/lib/python3.8/site-packages/libdeda/privacy.py", line 23, in <module>
    import libdeda.pypdf2patch
  File "/home/wesjo/.local/lib/python3.8/site-packages/libdeda/pypdf2patch.py", line 7, in <module>
    from PyPDF2 import pdf
ImportError: cannot import name 'pdf' from 'PyPDF2' (/home/wesjo/.local/lib/python3.8/site-packages/PyPDF2/__init__.py)

======================================
This was on a fresh install of ubuntu 20.04 with no custom config.
Linux ubuntu 5.13.0-52-generic #59~20.04.1-Ubuntu SMP Thu Jun 16 21:21:28 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux

Also tried first on kali linux.

unrecognised dots

Our Kyocera printer has the tracking dots which can be seen using graphic software easily (they're literally over the entire page when green channel levels are adjusted), however deda is not recognizing the dots in a 600dpi PNG.

I can't see any options for threshold or anything else. Is there anything I should try or would you accept an example for further developments?

Using deda_create_dots on a PDF changes the length of the page

When I use create_dots on a PDF file the length of the page increase from 11 to 12 inches. It writes the dots on a separate area on top of the page instead of incorporating them into the document. This means the documents I am printing will be a different size, and will not take up the full page. Is this how it is supposed to work?

Getting attribute error when calling 'numerator'

I have followed the installation instructions, but whenever I called the python file deda_parse_print.py with my scanned image, I am getting an the following error in the extract_yd.py file:

 dpi = [n.numerator for n in pilimg.info["dpi"]]
AttributeError: 'float' object has no attribute 'numerator'

Once I corrected the code to
dpi = [int(n).numerator for n in pilimg.info["dpi"]]
the error went away and I was able to run your Python script.

Cant detect a pattern

I am trying to anonymise a document for printing
I cant seem to detect my pattern
Ive tried printing my calibration test page and scanning it many times, with bmp tiff and png. Ive tried 300 600 1200 dpi. Ive tried all sorts of margins. No matter what I do I cant detect the pattern

I am able to zoom in on my image and indeed see the yellow marks with my own eyes
I am also able to detect the tracking dot with deda_extract_yd Detected tracking dot pattern

Is there any way to turn a unknown pattern into a recognized pattern @timojuez

❯ /home/pi/deda/deda_bin/deda_anonmask_create_img.py -r Image\ \(5\).png
Traceback (most recent call last):
  File "/home/pi/deda/deda_bin/deda_anonmask_create_img.py", line 46, in <module>
    Main()()
  File "/home/pi/deda/deda_bin/deda_anonmask_create_img.py", line 39, in __call__
    mask = calibrationScan2Anonmask(image_data, self.args.copy)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/root/.local/lib/python3.11/site-packages/libdeda/privacy.py", line 273, in calibrationScan2Anonmask
    return AnonmaskCreator(imbin,verbose)(copy)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/root/.local/lib/python3.11/site-packages/libdeda/privacy.py", line 105, in __call__
    self.restoreSkewByDots()
  File "/root/.local/lib/python3.11/site-packages/libdeda/privacy.py", line 184, in restoreSkewByDots
    pp = PrintParser(self.im,ydxArgs=dict(
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/root/.local/lib/python3.11/site-packages/libdeda/print_parser.py", line 78, in __init__
    raise exceptions[0]
  File "/root/.local/lib/python3.11/site-packages/libdeda/print_parser.py", line 68, in __init__
    self.pattern = self._calcPattern()
                   ^^^^^^^^^^^^^^^^^^^
  File "/root/.local/lib/python3.11/site-packages/libdeda/print_parser.py", line 145, in _calcPattern
    raise YD_Parsing_Error("Cannot detect pattern.",self.yd)
libdeda.print_parser.YD_Parsing_Error: Cannot detect pattern.   

AttributeError: module 'numpy' has no attribute 'object'.

FYI you need to edit /root/.local/lib/python3.11/site-packages/libdeda/privacy.py
replace
dtype=np.object)
with
dtype=object)

due to this error:

❯ deda_anonmask_create -r Image.png
/root/.local/lib/python3.11/site-packages/libdeda/privacy.py:143: FutureWarning: In the future `np.object` will be defined as the corresponding NumPy scalar.
  dtype=np.object)
Traceback (most recent call last):
  File "/root/.local/bin/deda_anonmask_create", line 8, in <module>
    sys.exit(main())
             ^^^^^^
  File "/root/.local/lib/python3.11/site-packages/deda_bin/deda_anonmask_create.py", line 50, in <lambda>
    main = lambda:Main()()
                  ^^^^^^^^
  File "/root/.local/lib/python3.11/site-packages/deda_bin/deda_anonmask_create.py", line 43, in __call__
    mask = calibrationScan2Anonmask(fp.read(),self.args.copy)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/root/.local/lib/python3.11/site-packages/libdeda/privacy.py", line 273, in calibrationScan2Anonmask
    return AnonmaskCreator(imbin,verbose)(copy)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/root/.local/lib/python3.11/site-packages/libdeda/privacy.py", line 104, in __call__
    self.restoreOrientation()
  File "/root/.local/lib/python3.11/site-packages/libdeda/privacy.py", line 150, in restoreOrientation
    contours = self._findContours(CYAN)
               ^^^^^^^^^^^^^^^^^^^^^^^^
  File "/root/.local/lib/python3.11/site-packages/libdeda/privacy.py", line 143, in _findContours
    dtype=np.object)
          ^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/numpy/__init__.py", line 324, in __getattr__
    raise AttributeError(__former_attrs__[attr])
AttributeError: module 'numpy' has no attribute 'object'.
`np.object` was a deprecated alias for the builtin `object`. To avoid this error in existing code, use `object` by itself. Doing this will not modify any behavior and is safe.
The aliases was originally deprecated in NumPy 1.20; for more details and guidance see the original release note at:
    https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations. Did you mean: 'object_'?    

ImportError: cannot import name 'main'

I installed DeDa on different platforms but wherever I am running a command, it returns an error:

ImportError: cannot import name 'main'

Command (example):

deda_clean_document test.tif

deda was installed via pip3 install deda and all components were downloaded and installed. Everything was successful, but I just can't run any of the commands.

Last attempt was OpenSuSE an pip 10.0.1.

eel 'options' deprecated

$ python --version
Python 3.7.4
$ python -m venv venv
$ source venv/bin/activate
$ pip install deda
$ deda_gui
Traceback (most recent call last):
  File "/tmp/deda/venv/bin/deda_gui", line 10, in <module>
    sys.exit(main())
  File "/tmp/deda/venv/lib/python3.7/site-packages/deda_gui/deda_gui.py", line 415, in main
    eel.start('index.html', options=web_app_options)
  File "/tmp/deda/venv/lib/python3.7/site-packages/eel/__init__.py", line 118, in start
    raise RuntimeError(api_error_message)
RuntimeError: 
----------------------------------------------------------------------------------
  'options' argument deprecated in v1.0.0, see https://github.com/ChrisKnott/Eel
  To suppress this error, add 'suppress_error=True' to start() call.
  This option will be removed in future versions
----------------------------------------------------------------------------------

Unable to find tracking dots - Fuji XEROX

Hi,

Thanks for this open source code. However I have an issue: i have multiple samples (more than 10) of FUJI xerox prints with tracking dots clear enough to be seen via simple image processing software, but for all these samples the program said 'no tracking dots found'. I scanned at 300dpi and tried both with auto-exposure and without (no corrections). I also tried enhancing the dots in imageJ but it does not work still. Can you help me? Thanks so much!

Exception "too many indices for array"

Hi,
after scanning the testpage I'd like to convert it to a mask. So I ran "deda_anonmask_create -r Testpage.bmp" and got the following error:
Traceback (most recent call last): File "C:\...\deda_anonmask_create-script.py", line 11, in <module> load_entry_point('deda==2.0b1', 'console_scripts', 'deda_anonmask_create')() File "C:\...\deda_anonmask_create.py", line 50, in <lambda> main = lambda:Main()() File "C:\...\deda_anonmask_create.py", line 43, in __call__ mask = calibrationScan2Anonmask(fp.read(),self.args.copy) File "C:\...\privacy.py", line 274, in calibrationScan2Anonmask return AnonmaskCreator(imbin,verbose)(copy) File "C:\...\privacy.py", line 105, in __call__ self.restoreOrientation() File "C:\...privacy.py", line 153, in restoreOrientation dot = np.min(cEdges[:,0]), np.min(cEdges[:,1]) IndexError: too many indices for array: array is 1-dimensional, but 2 were indexed
When I analyze the scanned file with Photoshop, I can clearly see the dots. The testpage was printed on a Kyocera printer.
Am I doing something wrong?
Thank you in advance!

PIL.UnidentifiedImageError: cannot identify image file <_io.BytesIO object at 0x7ffeefadcfe0>

❯ deda_anonmask_create -w
testpage.pdf written.                                                                                                                                    
❯ deda_parse_print testpage.pdf
Traceback (most recent call last):
  File "/root/.local/bin/deda_parse_print", line 8, in <module>
    sys.exit(main())
             ^^^^^^
  File "/root/.local/lib/python3.11/site-packages/deda_bin/deda_parse_print.py", line 83, in <lambda>
    main = lambda:Main()()
                  ^^^^^^^^
  File "/root/.local/lib/python3.11/site-packages/deda_bin/deda_parse_print.py", line 40, in __call__
    pp = PrintParser(fp.read(),ydxArgs=dict(mask=self.args.mask,
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/root/.local/lib/python3.11/site-packages/libdeda/print_parser.py", line 67, in __init__
    self._createYD_instance(ydColourRange=cp)
  File "/root/.local/lib/python3.11/site-packages/libdeda/print_parser.py", line 87, in _createYD_instance
    yd = YDX(**ydxArgs)
         ^^^^^^^^^^^^^^
  File "/root/.local/lib/python3.11/site-packages/libdeda/extract_yd.py", line 616, in __init__
    CommonImageFunctions.__init__(
  File "/root/.local/lib/python3.11/site-packages/libdeda/extract_yd.py", line 136, in __init__
    self.imgDpi = inputDpi if inputDpi else self.getImgDpi(image)
                                            ^^^^^^^^^^^^^^^^^^^^^
  File "/root/.local/lib/python3.11/site-packages/libdeda/extract_yd.py", line 143, in getImgDpi
    with Image.open(im) as pilimg:
         ^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/PIL/Image.py", line 3283, in open
    raise UnidentifiedImageError(msg)
PIL.UnidentifiedImageError: cannot identify image file <_io.BytesIO object at 0x7fff174d6ac0>  

Clarification of the documentation?

Optional requirement by deda_anonmask_apply (GNU/Linux only): $ pip3 install wand

  1. Is wand not required on Mac OS X?
  2. Don't you need to be root to install wand like that or shouldn't it be installed with --user ?

CUPS filter

There should be a CUPS filter you can add to your configuration (or something similar on Windows) so you can simply print and have the filter take care of adding in the dots.

Undefined names

flake8 testing of https://github.com/dfd-tud/deda on Python 3.6.3

$ flake8 . --count --select=E901,E999,F821,F822,F823 --show-source --statistics

./libdeda/extract_yd.py:192:25: F821 undefined name 'A'
            plt.scatter(A[:,1], A[:,0]*-1);
                        ^
./libdeda/extract_yd.py:192:33: F821 undefined name 'A'
            plt.scatter(A[:,1], A[:,0]*-1);
                                ^
./libdeda/extract_yd.py:193:25: F821 undefined name 'A'
            plt.scatter(A[mask2][:,1], A[mask2][:,0]*-1,color="r");
                        ^
./libdeda/extract_yd.py:193:40: F821 undefined name 'A'
            plt.scatter(A[mask2][:,1], A[mask2][:,0]*-1,color="r");
                                       ^
./libdeda/extract_yd.py:194:25: F821 undefined name 'B'
            plt.scatter(B[mask2][:,1], B[mask2][:,0]*-1,color="g");
                        ^
./libdeda/extract_yd.py:194:40: F821 undefined name 'B'
            plt.scatter(B[mask2][:,1], B[mask2][:,0]*-1,color="g");
                                       ^
./libdeda/pattern_handler.py:434:24: F821 undefined name 'parser'
        return getattr(parser,name)(self.m)
                       ^
7     F821 undefined name 'A'
7

wand.exceptions.PolicyError

There appears the error on wand operations:
wand.exceptions.PolicyError: attempt to perform an operation not allowed by the security policy PDF' @ error/constitute.c/IsCoderAuthorized/408

Not sure what we can do, this is a wand issue. Workaround: Add this <policy domain="coder" rights="read | write" pattern="PDF" /> just before </policymap> in /etc/ImageMagick-*/policy.xml.

See https://stackoverflow.com/questions/52998331/imagemagick-security-policy-pdf-blocking-conversion

known exceptions

I have a Samsung printer (CLP 320) and it does not seem to produce yd. Is there a list of known limitations of the script?

steps taken

I have printed the calibration.pdf, scanned that in 600dpi color to pnm, converted to losless tiff and analyzed using deda. I could drop the raw scan somewhere, if you are interested in analysing it.

▶ deda_extract_yd scan/SnapScanLossless00001.tiff                      
No tracking dot pattern found :-) (0.000001 yellow dots per inch)

then the script fails with stack trace

Traceback (most recent call last):
  File "/home/matthias/.local/bin/deda_extract_yd", line 10, in <module>
    sys.exit(main())
  File "/home/matthias/.local/lib/python3.7/site-packages/libdeda/extract_yd.py", line 888, in <lambda>
    main = lambda: Main()()
  File "/home/matthias/.local/lib/python3.7/site-packages/libdeda/extract_yd.py", line 91, in __call__
    noCrop=self.args.no_crop)
  File "/home/matthias/.local/lib/python3.7/site-packages/libdeda/extract_yd.py", line 846, in __init__
    self.cleanDotPositions(rotation=not noRotation,crop=not noCrop)
  File "/home/matthias/.local/lib/python3.7/site-packages/libdeda/extract_yd.py", line 673, in cleanDotPositions
    self.rotation = -self.getAngle(self.dots)
AttributeError: 'YellowDotsXposer' object has no attribute 'dots'

Exception will occur on some png files

On some png files it will fails with:

./deda_parse_print.py a.png

Traceback (most recent call last):
  File "./deda_parse_print.py", line 77, in <module>
    Main()()
  File "./deda_parse_print.py", line 41, in __call__
    verbose=self.args.verbose)
  File "/tmp/deda/libdeda/print_parser.py", line 88, in __init__
    self.pattern = self._calcPattern()
  File "/tmp/deda/libdeda/print_parser.py", line 152, in _calcPattern
    if len(ci)>0 and patternLimits[ci[0][0]] == -1:
UnboundLocalError: local variable 'ci' referenced before assignment

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.