<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://boofcv.org/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Orfgen</id>
	<title>BoofCV - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://boofcv.org/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Orfgen"/>
	<link rel="alternate" type="text/html" href="https://boofcv.org/index.php?title=Special:Contributions/Orfgen"/>
	<updated>2026-05-14T21:22:18Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.36.2</generator>
	<entry>
		<id>https://boofcv.org/index.php?title=Tutorial_Fiducials&amp;diff=2162</id>
		<title>Tutorial Fiducials</title>
		<link rel="alternate" type="text/html" href="https://boofcv.org/index.php?title=Tutorial_Fiducials&amp;diff=2162"/>
		<updated>2017-04-22T19:10:42Z</updated>

		<summary type="html">&lt;p&gt;Orfgen: /* Square Image */ Corrected github link &amp;quot;applet&amp;quot; -&amp;gt; &amp;quot;example&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;center&amp;gt;&lt;br /&gt;
&amp;lt;gallery caption=&amp;quot;Supported Fiducials&amp;quot; heights=200 widths=200 &amp;gt;&lt;br /&gt;
Image:Fiducial_squre_binary.png| Square Binary&lt;br /&gt;
Image:Fiducial_square_image.png| Square Image&lt;br /&gt;
Image:Calib_target_chess_small.png| Calibration Target&lt;br /&gt;
Image:Fiducial square binary detected.jpg| Cubes rendered on top of detected fiducials&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In computer vision, a fiducial marker is a known object which can be easily identified.  BoofCV provides built in support several different fiducials, all of which can be easily printed on paper.  Applications are provided for creating your own postscript files.  BoofCV library provides a single high level interface for detection, identification and pose estimation of all fiducials. Alternatively you can use the low level API and access fiducial specific information.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[https://youtu.be/qJWDK_FrgHE Fiducial Video Overview]&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are two types of fiducials supported in BoofCV, square and calibration targets.  Square fiducials encode a large number of unique patterns inside a black square box.  These targets can be uniquely identified and provide a full pose estimate.  Calibration targets fiducials are repurposed targets used to calibrate cameras.  Calibration fiducials tend to provide very accurate pose estimation when close to the camera, but can have difficulty as they move away.  There are two significant disadvantage for calibration targets. 1) They don&amp;#039;t provide a unique ID.  2) Most patterns are not fully orientation invariant.  You can see the lack of rotation invariance when it suddenly flips 180 degrees.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Fiducial Summary Table&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Type        !! Variant     !! Speed (FPS)  !! Unique    !! Pose    !! Accuracy&lt;br /&gt;
|-&lt;br /&gt;
|Square Binary|| Fast        ||style=&amp;quot;text-align:center;&amp;quot;| 175          || Varies    || Full    || Good&lt;br /&gt;
|-&lt;br /&gt;
|             || Robust      ||style=&amp;quot;text-align:center;&amp;quot;| 67           ||           ||         ||&lt;br /&gt;
|-&lt;br /&gt;
|Square Image || Fast        ||style=&amp;quot;text-align:center;&amp;quot;| 170          || &amp;amp;infin;   || Full    || Good&lt;br /&gt;
|-&lt;br /&gt;
|             || Robust      ||style=&amp;quot;text-align:center;&amp;quot;| 66           ||           ||         ||&lt;br /&gt;
|-&lt;br /&gt;
|Calibration  || Chessboard  ||style=&amp;quot;text-align:center;&amp;quot;| 97           || 1         || Partial || Best Close&lt;br /&gt;
|-&lt;br /&gt;
|             || Square Grid ||style=&amp;quot;text-align:center;&amp;quot;| 100          || 1         || Partial || Best Close&lt;br /&gt;
|}&lt;br /&gt;
&amp;#039;&amp;#039;Speed&amp;#039;&amp;#039; to detect multiple fiducials in a 640x480 image on a Intel Core i7-2600 3.4 Ghz.  &amp;#039;&amp;#039;Unique&amp;#039;&amp;#039; max number of unique targets it can identify.  &amp;#039;&amp;#039;Pose&amp;#039;&amp;#039; indicates if a full 6-DOF estimate is found or subset.  Infinity symbol really means &amp;quot;lots&amp;quot;.   Binary fiducials can be configured with different inner grids.  Total number of unique fiducials will very from 32 to 1.15e18 for a 3x3 or 8x8 grid, respectively.&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Quick Start =&lt;br /&gt;
&lt;br /&gt;
# Calibrate your camera and save results ([[Tutorial_Camera_Calibration|Tutorial]])&lt;br /&gt;
#* Technically optional, but highly recommended&lt;br /&gt;
# Print binary fiducial, e.g. [http://boofcv.org/notwiki/fiducials/square0643.eps Binary #0643]&lt;br /&gt;
# Launch fiducial webcam application&lt;br /&gt;
# Point camera at fiducial&lt;br /&gt;
&lt;br /&gt;
== Application ==&lt;br /&gt;
&lt;br /&gt;
To help you get started and quickly test ideas there&amp;#039;s a fiducial application included with BoofCV.  It will detect fiducials, then draw a 1/2 cube on top of them so you can see how accurate its 3D estimate is.  To run the application do the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
cd boofcv/applications&lt;br /&gt;
gradle applicationsJar&lt;br /&gt;
java -jar applications.jar WebcamTrackFiducial --Resolution=640:480 BINARY&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you calibrated your camera you can do the following and get better results:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
java -jar applications.jar WebcamTrackFiducial --Intrinsic=intrinsic.xml BINARY&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To get a list of commands and see how to track other types of fiducials just enter the command with no arguments.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
java -jar applications.jar WebcamTrackFiducial&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Printable Fiducials ==&lt;br /&gt;
&lt;br /&gt;
The following is a printable documents for all the types of fiducials supported in BoofCV.  Print these to get started quickly, but creating your own is also easy.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Square Binary !!  Chessboard &lt;br /&gt;
|-&lt;br /&gt;
| &lt;br /&gt;
* [http://boofcv.org/notwiki/fiducials/square0643.eps File 4x4 Binary #0643]&lt;br /&gt;
* [http://boofcv.org/notwiki/fiducials/square0284.eps File 4x4 Binary #0284]&lt;br /&gt;
| &lt;br /&gt;
* [http://boofcv.org/notwiki/calibration/letter_chess.ps Letter Sized Paper: Chessboard, 5 by 7, 30mm Squares]&lt;br /&gt;
* [http://boofcv.org/notwiki/calibration/A4_chess.ps A4 Sized Paper: Chessboard, 5 by 8, 30mm Squares]&lt;br /&gt;
* [http://boofcv.org/notwiki/calibration/A1_chess.ps A1 Sized Paper: Chessboard, 8 by 12, 60mm Squares]&lt;br /&gt;
|-&lt;br /&gt;
! Square Image !! Square grid&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
* [http://boofcv.org/notwiki/fiducials/10cm_pentarose.eps Pentarose]&lt;br /&gt;
* [http://boofcv.org/notwiki/fiducials/10cm_yinyang.eps Yin Yang]&lt;br /&gt;
* [http://boofcv.org/notwiki/fiducials/all_a4.eps Sheet of All, A4]&lt;br /&gt;
* [http://boofcv.org/notwiki/fiducials/all_letter.eps Sheet of All, Letter]&lt;br /&gt;
* [https://github.com/lessthanoptimal/BoofCV-Data/tree/master/applet/fiducial/image/eps bunch more]&lt;br /&gt;
|&lt;br /&gt;
* [http://boofcv.org/notwiki/calibration/letter_square.ps Letter Sized Paper: Square Grid, 3 by 4, 30mm Squares]&lt;br /&gt;
* [http://boofcv.org/notwiki/calibration/A4_square.ps A4 Sized Paper: Square Grid, 3 by 5, 30mm Squares]&lt;br /&gt;
* [http://boofcv.org/notwiki/calibration/A1_square.ps A1 Sized Paper: Square Grid, 4 by 6 60mm Squares]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Creating your Own Fiducial =&lt;br /&gt;
&lt;br /&gt;
For square fiducials, a convenient command-line application is provided which can create printable postscript (.ps) documents which contain one or more fiducials on them.  For calibration targets, prefabricated patterns are provided which can also be printed.&lt;br /&gt;
&lt;br /&gt;
== Square Binary ==&lt;br /&gt;
Fiducials can be made using the applications.jar you created earlier.  Usual for complete instructions just enter in the classes name with no arguments.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
java -jar applications.jar CreateFiducialSquareBinary -OutputFile=fiducial.ps -PrintInfo -Units=cm 12 284&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That will create a printable fiducial.ps file that encodes the number 284 in a 4x4 square that&amp;#039;s 12 centimeters.  The number of elements which compose its inner grid and the width of the outside border are both configurable.  By default all code assumes a 4x4 grid and 0.25 fractional border width.  This produces a reasonable compose between detection robustness and the number of features it can encode, which is 4096.&lt;br /&gt;
&lt;br /&gt;
== Square Image ==&lt;br /&gt;
&lt;br /&gt;
A fiducial can be easily created from any image using &amp;quot;applications.jar&amp;quot;.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
java -jar applications.jar CreateFiducialSquareImage -OutputFile=fiducial.ps -PrintInfo -Units=cm 12 pentarose.png&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
This will create a pattern which is 12cm wide and encodes the image contained in &amp;#039;pentarose.png&amp;#039;.  The output will be saved in &amp;quot;fiducial.ps&amp;quot; file.&lt;br /&gt;
&lt;br /&gt;
Not feeling very creative or just want to see some example images?  Several patterns are contained in [https://github.com/lessthanoptimal/BoofCV-Data/tree/master/example/fiducial/image/patterns &amp;quot;data/example/fiducial/image/patterns/&amp;quot;].&lt;br /&gt;
&lt;br /&gt;
= How Do Square Fiducials Work? =&lt;br /&gt;
[[File:Square fiducial parts.png|thumb|300px|The origin of the fiducial is at its center with x and y axises as shown.  The fiducial itself can be divided into three regions, a) white outside region which provides contrast against the black border, b) black square border, and c) encoded image or pattern.]]&lt;br /&gt;
&lt;br /&gt;
All square fiducials share a common code base.  A target contains a black square of constant width and inside there is an image or pattern. The pattern is used to uniquely identify the fiducial and determine its orientation.  A full 6-DOF pose is estimated from these fiducials.  These targets are inspired by ARToolkit, but the code is not a port and was developed from scratched.  &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Processing Steps&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
# Create binary image by thresholding&lt;br /&gt;
# Contours of dark objects&lt;br /&gt;
# Contour to crude quadrilateral&lt;br /&gt;
# Sub-pixel refinement of quadrilateral&lt;br /&gt;
# Undistort quadrilateral image and match to known patterns&lt;br /&gt;
# Extract 3D pose of fiducial&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;Step 1:&amp;#039;&amp;#039; [[Example_Thresholding|Thresholding]] is performed using either a user configurable fixed threshold or locally adaptive threshold, fast and robust respectively. While slower robust can handle variations in lighting much better.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;Step 2:&amp;#039;&amp;#039; Contours are found from the binary blobs using [http://boofcv.org/javadoc/boofcv/alg/filter/binary/LinearContourLabelChang2004.html Chang 2004].&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;Step 3:&amp;#039;&amp;#039; The contour is converted into a polygon using a [[Example_Fit_Polygon|split and merge]] technique.  Only four sided polygons are accepted.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;Step 4:&amp;#039;&amp;#039; The crude polygons are refined to subpixel accuracy.  This is done by iteratively refining the estimate of each side&amp;#039;s line.  That is done by computing the difference of line integrals tangential to each line, then using their intensity values to compute a weighted line.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;Step 5:&amp;#039;&amp;#039; The four corners are now known to a high level of precision, these are then used to compute a homography which is then used to generate an undistorted square image of the inner pattern.  This pattern is then used by the specific algorithm to identify a known target or compute a number.  Noisy images are rejected here.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;Step 6:&amp;#039;&amp;#039; The pose is computed through a combination of [[Example_PnP|P3P and P4P]] techniques.  The one with the smallest residual error is selected.  Then non-linear refinement is performed. Care is taken to reduce the effects of head on small fiducials, which have a degenerate geometry.  In that situation significant changes in orientation result in only a small change on the image.  That is handled by placing a greater emphasis on reprojection error caused by orientation.&lt;br /&gt;
&lt;br /&gt;
NOTE: Steps 2 to 4 are carried out by the [[Example_Detect_Black_Polygons|black polygon detector]].&lt;br /&gt;
&lt;br /&gt;
== Square Binary ==&lt;br /&gt;
&lt;br /&gt;
The square binary fiducial encodes a 12-bit number, 4096 possible values, using a binary pattern. The number is encoded by breaking up the inner portion into 16 squares in a 4x4 grid. Three of the corners are always white and one black. This is how it resolves an orientation ambiguity. &lt;br /&gt;
&lt;br /&gt;
== Square Image ==&lt;br /&gt;
&lt;br /&gt;
When an image is loaded into this type of fiducial it is first converted into a square image then down sampled into a low resolution image and encoded efficiently .  When processing a video feed and a fiducial is detected the pattern is undistorted as usual. Then the hamming distance between the just observed pattern and all the known patterns is found.  The pattern with the best score within tolerance is accepted.&lt;br /&gt;
&lt;br /&gt;
= Programming =&lt;br /&gt;
&lt;br /&gt;
All of these different types of fiducials can be used through a high level interface, *FiducialDetector*.  FactoryFiducial is the easiest way to create instances of different fiducial types and it hides much of the complexity.  Some detectors require additional information after construction. For example, square image fiducials require images be provided for each target it can detect.  A sketch of how to process a single image is shown below.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
FiducialDetector&amp;lt;ImageFloat32&amp;gt; detector = FactoryFiducial.pickAFiducial(...);&lt;br /&gt;
... additional fiducial specific configuration goes here ...&lt;br /&gt;
detector.setIntrinsic(param);&lt;br /&gt;
detector.detect(image);&lt;br /&gt;
Se3_F64 targetToSensor = new Se3_F64();&lt;br /&gt;
for (int i = 0; i &amp;lt; detector.totalFound(); i++){&lt;br /&gt;
	System.out.println(&amp;quot;Target ID = &amp;quot;+detector.getId(i));&lt;br /&gt;
	System.out.println(&amp;quot;Target width = &amp;quot;+detector.getWidth(i));&lt;br /&gt;
	detector.getFiducialToWorld(i,targetToSensor);&lt;br /&gt;
	System.out.println(&amp;quot;Location:&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See the examples below for a more understanding of how to use these different types of fiducials.&lt;br /&gt;
&lt;br /&gt;
Applets:&lt;br /&gt;
* [[Applet_Fiducials| Applet Fiducials]]&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
* [[Example Fiducial Square Binary| Square Binary Example]]&lt;br /&gt;
* [[Example Fiducial Square Image| Square Image Example]]&lt;br /&gt;
* [[Example_Calibration_Target_Pose|Calibration Target Example]]&lt;/div&gt;</summary>
		<author><name>Orfgen</name></author>
	</entry>
	<entry>
		<id>https://boofcv.org/index.php?title=Talk:Tutorial_Quick_Start&amp;diff=2161</id>
		<title>Talk:Tutorial Quick Start</title>
		<link rel="alternate" type="text/html" href="https://boofcv.org/index.php?title=Talk:Tutorial_Quick_Start&amp;diff=2161"/>
		<updated>2017-04-21T21:09:36Z</updated>

		<summary type="html">&lt;p&gt;Orfgen: Added short list of methods that do not exist in 0.26, but are given as example here.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;These methods from the filter section do not exist anymore:&lt;br /&gt;
FactoryImageBorder.extend(input);&lt;br /&gt;
GImageDerivativeOps.sobel(blurred, derivX, derivY, BorderType.EXTENDED);&lt;br /&gt;
AnyImageDerivative&amp;lt;T,D&amp;gt; deriv = GImageDerivativeOps.createDerivatives((Class&amp;lt;T&amp;gt;)input.getClass(),derivType);&lt;/div&gt;</summary>
		<author><name>Orfgen</name></author>
	</entry>
	<entry>
		<id>https://boofcv.org/index.php?title=Tutorial_Quick_Start&amp;diff=2160</id>
		<title>Tutorial Quick Start</title>
		<link rel="alternate" type="text/html" href="https://boofcv.org/index.php?title=Tutorial_Quick_Start&amp;diff=2160"/>
		<updated>2017-04-21T21:02:38Z</updated>

		<summary type="html">&lt;p&gt;Orfgen: /* Filters */ createImage -&amp;gt; createSingleBand&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The following tutorial is intended to provide just enough information for you to quickly set up and start development with BoofCV.  If you are not familiar with the [http://java.oracle.com Java programming language] or its associated development tools, you must fix that first because BoofCV is written entirely in Java. It is highly recommended that you use a tool like [https://gradle.org Gradle] to build your own project and have it download the jars for you.  If you enjoy doing things the slow and tedious way we are there for you and provide all the jars.&lt;br /&gt;
&lt;br /&gt;
== Step One: Obtaining ==&lt;br /&gt;
&lt;br /&gt;
The first step in using BoofCV is either adding it to your dependency list, downloading the precompiled Jars, or building it from Source. &lt;br /&gt;
&lt;br /&gt;
Latest Official Release:  &lt;br /&gt;
* Source Code [[Download:BoofCV|Download Page]]&lt;br /&gt;
* Jars [[Download:BoofCV|Download Page]]&lt;br /&gt;
* Maven and Gradle [[Download:BoofCV|Download Page]]&lt;br /&gt;
&lt;br /&gt;
== Step Two: Running Examples and Demonstrations ==&lt;br /&gt;
&lt;br /&gt;
Examples are short pieces of code which are designed to be easy to understand and show you how to perform some task.  Demonstrations are more complex applications which visualize different aspects of an algorithm.  The code for a demonstration is not designed to be easy to learn from and can be quite complex due to its integration with a GUI.&lt;br /&gt;
&lt;br /&gt;
Source Code:&lt;br /&gt;
* [https://github.com/lessthanoptimal/BoofCV/tree/master/examples boofcv/examples]&lt;br /&gt;
* [https://github.com/lessthanoptimal/BoofCV/tree/master/demonstrations boofcv/demonstrations]&lt;br /&gt;
&lt;br /&gt;
The easiest way to run an example or demonstration is to launch their respective master applications.  You can also load up the source code in your favorite IDE and run the applications directly.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
cd boofcv&lt;br /&gt;
./gradlew examples&lt;br /&gt;
java -jar examples/examples.jar&lt;br /&gt;
./gradlew demonstrations&lt;br /&gt;
java -jar demonstrations/demonstrations.jar&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= HELP ME!! =&lt;br /&gt;
&lt;br /&gt;
Having trouble or have a suggestion?  Post a message on the BoofCV message board! Don&amp;#039;t worry it&amp;#039;s a friendly place.&lt;br /&gt;
* [http://groups.google.com/group/boofcv Message Board]  &lt;br /&gt;
&lt;br /&gt;
= Quick Reference =&lt;br /&gt;
&lt;br /&gt;
The remainder of this tutorial is intended to act as a quick reference of low level image processing routines in BoofCV.  &lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Term !! definition&lt;br /&gt;
|-&lt;br /&gt;
| single band || The image supports only one color&lt;br /&gt;
|-&lt;br /&gt;
| floating point || Image elements are of type float or double&lt;br /&gt;
|-&lt;br /&gt;
| unsigned || Image elements can only be positive integers&lt;br /&gt;
|-&lt;br /&gt;
| signed || Image elements can be either positive or negative integers&lt;br /&gt;
|-&lt;br /&gt;
| generics || Allows strong typing in abstracted code.  Introduced in Java 1.5.  Click [http://docs.oracle.com/javase/tutorial/java/generics/index.html here].&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The Basics ==&lt;br /&gt;
&lt;br /&gt;
BoofCV supports 3 types of images; Gray (single band images), Planar (multi-band in a planar format), and Interleaved (traditional multi-band image format).  The first two, gray and planar are fully supported while interleaved is partially supported.  Gray and planar images are just easier to work with most of the time which is why they are fully supported.  Interleaved is only supported where there is a performance advantage that was significant.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
GrayU8 image = new GrayU8(100,150);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Creating an unsigned 8-bit integer single band image with width=100 and height=150.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
GrayF32 image = new GrayF32(100,150);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Creating a floating point single band image with width=100 and height=150.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
Planar&amp;lt;GrayU8&amp;gt; image = new Planar&amp;lt;GrayU8&amp;gt;(GrayU8.class,100,200,3);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Creates a color planar image with 3 bands using GrayU8 for each band.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
GrayF32 image = UtilImageIO.loadImage(&amp;quot;test.png&amp;quot;,GrayF32.class);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Loads a single band image of type GrayF32 from a file.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public static &amp;lt;T extends ImageBase&amp;gt; T generic( Class&amp;lt;T&amp;gt; imageType ) {&lt;br /&gt;
	T image = UtilImageIO.loadImage(&amp;quot;test.png&amp;quot;,imageType);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Loads an image with the specified type inside a function that uses Java generics.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
BufferedImage out = ConvertBufferedImage.convertTo(image,null);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Converts an image into a BufferedImage to provide better integration with Java2D (display/saving).  Pixel values must be in the range of 0 to 255.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
BufferedImage out = VisualizeImageData.grayMagnitude(derivX,null,-1);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Renders a signed single band image into a gray intensity image.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
BufferedImage out = VisualizeImageData.colorizeSign(derivX,null,-1);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Renders a signed single band image into a color intensity image.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
BufferedImage out = ConvertBufferedImage.convertTo(image,null);&lt;br /&gt;
ShowImages.showWindow(out,&amp;quot;Output&amp;quot;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Displays an image in a window using Java swing.&lt;br /&gt;
&lt;br /&gt;
== Pixel Access ==&lt;br /&gt;
&lt;br /&gt;
The image type must be known to access pixel information.  The following show how to access pixels for different image types.  For more information on the image data structure and direct access to the raw data array see [[Tutorial Images]] for more details&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public static void function( GrayF32 image )&lt;br /&gt;
{&lt;br /&gt;
	float pixel = image.get(5,23);&lt;br /&gt;
	image.set(5,23,50.3);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Gets and sets the pixel at (5,23).  Note that set() and get() functions are image type specific.  In other words, you can&amp;#039;t access pixel without knowing the image type.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public static void function( GrayU8 image )&lt;br /&gt;
{&lt;br /&gt;
	int pixel = image.get(5,23);&lt;br /&gt;
	image.set(5,23,50);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Similar to the above example but for an 8-bit unsigned integer image.  Note the image.get() returns &amp;#039;int&amp;#039; and not &amp;#039;byte&amp;#039;.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public static void function( GrayI image )&lt;br /&gt;
{&lt;br /&gt;
	int pixel = image.get(5,23);&lt;br /&gt;
	image.set(5,23,50);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
In fact the same code will work for all integer images, except SInt64 which uses longs and not ints. Internally UInt8 stores its pixels as a byte array, but set() and get() return int because Java internally does not use bytes on the register.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public static void function( Planar&amp;lt;GrayU8&amp;gt; image )&lt;br /&gt;
{&lt;br /&gt;
	int pixel = image.getBand(0).get(5,23);&lt;br /&gt;
	image.getBand(0).set(5,23,50);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Planar images are essentially arrays of ImageGray.  To set or get a pixel value first access the particular band that needs to be changed then use the standard accessors inside of ImageSingleBand.&lt;br /&gt;
&lt;br /&gt;
== Filters ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public static void procedural( GrayU8 input )&lt;br /&gt;
{&lt;br /&gt;
	GrayU8 blurred = new GrayU8(input.width,input.height);&lt;br /&gt;
	BlurImageOps.gaussian(input,blurred,-1,blurRadius,null);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Applies Gaussian blur to an image using a type specific procedural interface.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public static &amp;lt;T extends ImageGray, D extends ImageGray&amp;gt;&lt;br /&gt;
void generalized( T input )&lt;br /&gt;
{&lt;br /&gt;
	Class&amp;lt;T&amp;gt; inputType = (Class&amp;lt;T&amp;gt;)input.getClass();&lt;br /&gt;
&lt;br /&gt;
	T blurred = GeneralizedImageOps.createSingleBand(inputType,input.width, input.height);&lt;br /&gt;
	GBlurImageOps.gaussian(input, blurred, -1, blurRadius, null);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Applies Gaussian blur to an image using an abstracted procedural interface.  Note the G in front of BlurImageOps that indicates&lt;br /&gt;
it contains generic functions. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public static &amp;lt;T extends ImageGray, D extends ImageGray&amp;gt;&lt;br /&gt;
void filter( T input )&lt;br /&gt;
{&lt;br /&gt;
	Class&amp;lt;T&amp;gt; inputType = (Class&amp;lt;T&amp;gt;)input.getClass();&lt;br /&gt;
	T blurred = GeneralizedImageOps.createSingleBand(inputType, input.width, input.height);&lt;br /&gt;
	BlurFilter&amp;lt;T&amp;gt; filterBlur = FactoryBlurFilter.gaussian(inputType, -1, blurRadius);&lt;br /&gt;
	filterBlur.process(input,blurred);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Creates an image filter class for computing the Gaussian blur.  Provides greater abstraction.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
// type specific sobel&lt;br /&gt;
GradientSobel.process(blurred, derivX, derivY, FactoryImageBorder.extend(input));&lt;br /&gt;
// generic&lt;br /&gt;
GImageDerivativeOps.sobel(blurred, derivX, derivY, BorderType.EXTENDED);&lt;br /&gt;
// filter&lt;br /&gt;
ImageGradient&amp;lt;T,D&amp;gt; gradient = FactoryDerivative.sobel(inputType, derivType);&lt;br /&gt;
gradient.process(blurred,derivX,derivY);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Three ways to compute the image gradient using a Sobel kernel.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public static &amp;lt;T extends ImageGray, D extends ImageGray&amp;gt;&lt;br /&gt;
void example( T input , Class&amp;lt;D&amp;gt; derivType ) {&lt;br /&gt;
	AnyImageDerivative&amp;lt;T,D&amp;gt; deriv = GImageDerivativeOps.createDerivatives((Class&amp;lt;T&amp;gt;)input.getClass(),derivType);&lt;br /&gt;
&lt;br /&gt;
	deriv.setInput(input);&lt;br /&gt;
	D derivX = deriv.getDerivative(true);&lt;br /&gt;
	D derivXXY = deriv.getDerivative(true,true,false);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Useful class for computing arbitrary image derivatives.  Computes 1st order x-derive and then 3rd order xxy derivative.&lt;br /&gt;
&lt;br /&gt;
== Binary Images ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
ThresholdImageOps.threshold(image, binary, 23, true);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Creates a binary image by thresholding the input image.  Binary must be of type GrayU8.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
binary = BinaryImageOps.erode8(binary, 1, null);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Apply an erode operation once on the binary image, writing over the original image reference.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
BinaryImageOps.erode8(binary, 1, output);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Apply an erode operation once on the binary image, saving results to the output binary image.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
BinaryImageOps.erode4(binary, 1, output);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Apply an erode operation once with a 4-connect rule.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
int numBlobs = BinaryImageOps.contour(binary, ConnectRule.FOUR, blobs).size();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Detect and label blobs in the binary image using a 4-connect rule.  blobs is an image of type GrayS32.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
BufferedImage visualized = VisualizeBinaryData.renderLabeled(blobs, numBlobs, null);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Renders the detected blobs in a colored image.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
BufferedImage visualized = VisualizeBinaryData.renderBinary(binary, false, null);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Renders the binary image as a black white image. false means the colors are not inverted.&lt;br /&gt;
&lt;br /&gt;
== Suggested Hardware ==&lt;br /&gt;
&lt;br /&gt;
To do computer vision you need a camera.  Here&amp;#039;s a list of recommended cameras&lt;br /&gt;
&lt;br /&gt;
* [http://amzn.to/2igJ9GC Webcam: Logitech C920]&lt;br /&gt;
* [http://amzn.to/2hWGohn 360 Camera: Theta S ]&lt;br /&gt;
&lt;br /&gt;
Webcams are great for basically everything but structure from motion (SFM) applications.  Their images often look better than much more expensive scientific cameras.  Unfortunately they have a rolling shutter which breaks SFM algorithms if anything in the scene or the camera is moving.&lt;br /&gt;
&lt;br /&gt;
The Theta S is a 360 camera composed of two fisheye cameras.  Interestingly it is one of the few consumer grade cameras to provide a global shutter!  Making it useful for SFM applications.&lt;br /&gt;
&lt;br /&gt;
(The above links are Amazon affiliate.  If you do plan on purchasing one of those cameras please help finance BoofCV and click on those links.)&lt;/div&gt;</summary>
		<author><name>Orfgen</name></author>
	</entry>
	<entry>
		<id>https://boofcv.org/index.php?title=Tutorial_Quick_Start&amp;diff=2159</id>
		<title>Tutorial Quick Start</title>
		<link rel="alternate" type="text/html" href="https://boofcv.org/index.php?title=Tutorial_Quick_Start&amp;diff=2159"/>
		<updated>2017-04-21T20:44:09Z</updated>

		<summary type="html">&lt;p&gt;Orfgen: Changed Binary Images code to 0.26&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The following tutorial is intended to provide just enough information for you to quickly set up and start development with BoofCV.  If you are not familiar with the [http://java.oracle.com Java programming language] or its associated development tools, you must fix that first because BoofCV is written entirely in Java. It is highly recommended that you use a tool like [https://gradle.org Gradle] to build your own project and have it download the jars for you.  If you enjoy doing things the slow and tedious way we are there for you and provide all the jars.&lt;br /&gt;
&lt;br /&gt;
== Step One: Obtaining ==&lt;br /&gt;
&lt;br /&gt;
The first step in using BoofCV is either adding it to your dependency list, downloading the precompiled Jars, or building it from Source. &lt;br /&gt;
&lt;br /&gt;
Latest Official Release:  &lt;br /&gt;
* Source Code [[Download:BoofCV|Download Page]]&lt;br /&gt;
* Jars [[Download:BoofCV|Download Page]]&lt;br /&gt;
* Maven and Gradle [[Download:BoofCV|Download Page]]&lt;br /&gt;
&lt;br /&gt;
== Step Two: Running Examples and Demonstrations ==&lt;br /&gt;
&lt;br /&gt;
Examples are short pieces of code which are designed to be easy to understand and show you how to perform some task.  Demonstrations are more complex applications which visualize different aspects of an algorithm.  The code for a demonstration is not designed to be easy to learn from and can be quite complex due to its integration with a GUI.&lt;br /&gt;
&lt;br /&gt;
Source Code:&lt;br /&gt;
* [https://github.com/lessthanoptimal/BoofCV/tree/master/examples boofcv/examples]&lt;br /&gt;
* [https://github.com/lessthanoptimal/BoofCV/tree/master/demonstrations boofcv/demonstrations]&lt;br /&gt;
&lt;br /&gt;
The easiest way to run an example or demonstration is to launch their respective master applications.  You can also load up the source code in your favorite IDE and run the applications directly.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
cd boofcv&lt;br /&gt;
./gradlew examples&lt;br /&gt;
java -jar examples/examples.jar&lt;br /&gt;
./gradlew demonstrations&lt;br /&gt;
java -jar demonstrations/demonstrations.jar&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= HELP ME!! =&lt;br /&gt;
&lt;br /&gt;
Having trouble or have a suggestion?  Post a message on the BoofCV message board! Don&amp;#039;t worry it&amp;#039;s a friendly place.&lt;br /&gt;
* [http://groups.google.com/group/boofcv Message Board]  &lt;br /&gt;
&lt;br /&gt;
= Quick Reference =&lt;br /&gt;
&lt;br /&gt;
The remainder of this tutorial is intended to act as a quick reference of low level image processing routines in BoofCV.  &lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Term !! definition&lt;br /&gt;
|-&lt;br /&gt;
| single band || The image supports only one color&lt;br /&gt;
|-&lt;br /&gt;
| floating point || Image elements are of type float or double&lt;br /&gt;
|-&lt;br /&gt;
| unsigned || Image elements can only be positive integers&lt;br /&gt;
|-&lt;br /&gt;
| signed || Image elements can be either positive or negative integers&lt;br /&gt;
|-&lt;br /&gt;
| generics || Allows strong typing in abstracted code.  Introduced in Java 1.5.  Click [http://docs.oracle.com/javase/tutorial/java/generics/index.html here].&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The Basics ==&lt;br /&gt;
&lt;br /&gt;
BoofCV supports 3 types of images; Gray (single band images), Planar (multi-band in a planar format), and Interleaved (traditional multi-band image format).  The first two, gray and planar are fully supported while interleaved is partially supported.  Gray and planar images are just easier to work with most of the time which is why they are fully supported.  Interleaved is only supported where there is a performance advantage that was significant.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
GrayU8 image = new GrayU8(100,150);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Creating an unsigned 8-bit integer single band image with width=100 and height=150.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
GrayF32 image = new GrayF32(100,150);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Creating a floating point single band image with width=100 and height=150.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
Planar&amp;lt;GrayU8&amp;gt; image = new Planar&amp;lt;GrayU8&amp;gt;(GrayU8.class,100,200,3);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Creates a color planar image with 3 bands using GrayU8 for each band.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
GrayF32 image = UtilImageIO.loadImage(&amp;quot;test.png&amp;quot;,GrayF32.class);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Loads a single band image of type GrayF32 from a file.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public static &amp;lt;T extends ImageBase&amp;gt; T generic( Class&amp;lt;T&amp;gt; imageType ) {&lt;br /&gt;
	T image = UtilImageIO.loadImage(&amp;quot;test.png&amp;quot;,imageType);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Loads an image with the specified type inside a function that uses Java generics.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
BufferedImage out = ConvertBufferedImage.convertTo(image,null);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Converts an image into a BufferedImage to provide better integration with Java2D (display/saving).  Pixel values must be in the range of 0 to 255.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
BufferedImage out = VisualizeImageData.grayMagnitude(derivX,null,-1);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Renders a signed single band image into a gray intensity image.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
BufferedImage out = VisualizeImageData.colorizeSign(derivX,null,-1);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Renders a signed single band image into a color intensity image.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
BufferedImage out = ConvertBufferedImage.convertTo(image,null);&lt;br /&gt;
ShowImages.showWindow(out,&amp;quot;Output&amp;quot;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Displays an image in a window using Java swing.&lt;br /&gt;
&lt;br /&gt;
== Pixel Access ==&lt;br /&gt;
&lt;br /&gt;
The image type must be known to access pixel information.  The following show how to access pixels for different image types.  For more information on the image data structure and direct access to the raw data array see [[Tutorial Images]] for more details&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public static void function( GrayF32 image )&lt;br /&gt;
{&lt;br /&gt;
	float pixel = image.get(5,23);&lt;br /&gt;
	image.set(5,23,50.3);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Gets and sets the pixel at (5,23).  Note that set() and get() functions are image type specific.  In other words, you can&amp;#039;t access pixel without knowing the image type.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public static void function( GrayU8 image )&lt;br /&gt;
{&lt;br /&gt;
	int pixel = image.get(5,23);&lt;br /&gt;
	image.set(5,23,50);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Similar to the above example but for an 8-bit unsigned integer image.  Note the image.get() returns &amp;#039;int&amp;#039; and not &amp;#039;byte&amp;#039;.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public static void function( GrayI image )&lt;br /&gt;
{&lt;br /&gt;
	int pixel = image.get(5,23);&lt;br /&gt;
	image.set(5,23,50);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
In fact the same code will work for all integer images, except SInt64 which uses longs and not ints. Internally UInt8 stores its pixels as a byte array, but set() and get() return int because Java internally does not use bytes on the register.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public static void function( Planar&amp;lt;GrayU8&amp;gt; image )&lt;br /&gt;
{&lt;br /&gt;
	int pixel = image.getBand(0).get(5,23);&lt;br /&gt;
	image.getBand(0).set(5,23,50);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Planar images are essentially arrays of ImageGray.  To set or get a pixel value first access the particular band that needs to be changed then use the standard accessors inside of ImageSingleBand.&lt;br /&gt;
&lt;br /&gt;
== Filters ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public static void procedural( GrayU8 input )&lt;br /&gt;
{&lt;br /&gt;
	GrayU8 blurred = new GrayU8(input.width,input.height);&lt;br /&gt;
	BlurImageOps.gaussian(input,blurred,-1,blurRadius,null);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Applies Gaussian blur to an image using a type specific procedural interface.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public static &amp;lt;T extends ImageGray, D extends ImageGray&amp;gt;&lt;br /&gt;
void generalized( T input )&lt;br /&gt;
{&lt;br /&gt;
	Class&amp;lt;T&amp;gt; inputType = (Class&amp;lt;T&amp;gt;)input.getClass();&lt;br /&gt;
&lt;br /&gt;
	T blurred = GeneralizedImageOps.createImage(inputType,input.width, input.height);&lt;br /&gt;
	GBlurImageOps.gaussian(input, blurred, -1, blurRadius, null);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Applies Gaussian blur to an image using an abstracted procedural interface.  Note the G in front of BlurImageOps that indicates&lt;br /&gt;
it contains generic functions. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public static &amp;lt;T extends ImageGray, D extends ImageGray&amp;gt;&lt;br /&gt;
void filter( T input )&lt;br /&gt;
{&lt;br /&gt;
	Class&amp;lt;T&amp;gt; inputType = (Class&amp;lt;T&amp;gt;)input.getClass();&lt;br /&gt;
	T blurred = GeneralizedImageOps.createImage(inputType, input.width, input.height);&lt;br /&gt;
	BlurFilter&amp;lt;T&amp;gt; filterBlur = FactoryBlurFilter.gaussian(inputType, -1, blurRadius);&lt;br /&gt;
	filterBlur.process(input,blurred);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Creates an image filter class for computing the Gaussian blur.  Provides greater abstraction.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
// type specific sobel&lt;br /&gt;
GradientSobel.process(blurred, derivX, derivY, FactoryImageBorder.extend(input));&lt;br /&gt;
// generic&lt;br /&gt;
GImageDerivativeOps.sobel(blurred, derivX, derivY, BorderType.EXTENDED);&lt;br /&gt;
// filter&lt;br /&gt;
ImageGradient&amp;lt;T,D&amp;gt; gradient = FactoryDerivative.sobel(inputType, derivType);&lt;br /&gt;
gradient.process(blurred,derivX,derivY);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Three ways to compute the image gradient using a Sobel kernel.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public static &amp;lt;T extends ImageGray, D extends ImageGray&amp;gt;&lt;br /&gt;
void example( T input , Class&amp;lt;D&amp;gt; derivType ) {&lt;br /&gt;
	AnyImageDerivative&amp;lt;T,D&amp;gt; deriv = GImageDerivativeOps.createDerivatives((Class&amp;lt;T&amp;gt;)input.getClass(),derivType);&lt;br /&gt;
&lt;br /&gt;
	deriv.setInput(input);&lt;br /&gt;
	D derivX = deriv.getDerivative(true);&lt;br /&gt;
	D derivXXY = deriv.getDerivative(true,true,false);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Useful class for computing arbitrary image derivatives.  Computes 1st order x-derive and then 3rd order xxy derivative.&lt;br /&gt;
&lt;br /&gt;
== Binary Images ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
ThresholdImageOps.threshold(image, binary, 23, true);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Creates a binary image by thresholding the input image.  Binary must be of type GrayU8.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
binary = BinaryImageOps.erode8(binary, 1, null);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Apply an erode operation once on the binary image, writing over the original image reference.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
BinaryImageOps.erode8(binary, 1, output);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Apply an erode operation once on the binary image, saving results to the output binary image.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
BinaryImageOps.erode4(binary, 1, output);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Apply an erode operation once with a 4-connect rule.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
int numBlobs = BinaryImageOps.contour(binary, ConnectRule.FOUR, blobs).size();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Detect and label blobs in the binary image using a 4-connect rule.  blobs is an image of type GrayS32.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
BufferedImage visualized = VisualizeBinaryData.renderLabeled(blobs, numBlobs, null);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Renders the detected blobs in a colored image.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
BufferedImage visualized = VisualizeBinaryData.renderBinary(binary, false, null);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Renders the binary image as a black white image. false means the colors are not inverted.&lt;br /&gt;
&lt;br /&gt;
== Suggested Hardware ==&lt;br /&gt;
&lt;br /&gt;
To do computer vision you need a camera.  Here&amp;#039;s a list of recommended cameras&lt;br /&gt;
&lt;br /&gt;
* [http://amzn.to/2igJ9GC Webcam: Logitech C920]&lt;br /&gt;
* [http://amzn.to/2hWGohn 360 Camera: Theta S ]&lt;br /&gt;
&lt;br /&gt;
Webcams are great for basically everything but structure from motion (SFM) applications.  Their images often look better than much more expensive scientific cameras.  Unfortunately they have a rolling shutter which breaks SFM algorithms if anything in the scene or the camera is moving.&lt;br /&gt;
&lt;br /&gt;
The Theta S is a 360 camera composed of two fisheye cameras.  Interestingly it is one of the few consumer grade cameras to provide a global shutter!  Making it useful for SFM applications.&lt;br /&gt;
&lt;br /&gt;
(The above links are Amazon affiliate.  If you do plan on purchasing one of those cameras please help finance BoofCV and click on those links.)&lt;/div&gt;</summary>
		<author><name>Orfgen</name></author>
	</entry>
</feed>