Skip to content

Commit

Permalink
* Included new Blobs module from David Grossman and the correspond…
Browse files Browse the repository at this point in the history
…ing `BlobDemo` sample
  • Loading branch information
saudet committed Oct 8, 2012
1 parent 5b41901 commit 0bd7962
Show file tree
Hide file tree
Showing 10 changed files with 924 additions and 2 deletions.
5 changes: 3 additions & 2 deletions README.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
==Introduction==
JavaCV first provides wrappers to commonly used libraries by researchers in the field of computer vision: [http://opencv.willowgarage.com/ OpenCV], [http://www.ffmpeg.org/ FFmpeg], [http://damien.douxchamps.net/ieee1394/libdc1394/ libdc1394], [http://www.ptgrey.com/products/pgrflycapture/ PGR FlyCapture], [http://openkinect.org/ OpenKinect], [http://muonics.net/school/spring05/videoInput/ videoInput], and [http://studierstube.icg.tugraz.at/handheld_ar/artoolkitplus.php ARToolKitPlus]. The classes found under the `com.googlecode.javacv.cpp` package namespace expose their complete APIs. Moreover, utility classes make their functionality easier to use on the Java platform, including Android.

JavaCV also comes with hardware accelerated full-screen image display (`CanvasFrame` and `GLCanvasFrame`), easy-to-use methods to execute code in parallel on multiple cores (`Parallel`), user-friendly geometric and color calibration of cameras and projectors (`GeometricCalibrator`, `ProCamGeometricCalibrator`, `ProCamColorCalibrator`), detection and matching of feature points (`ObjectFinder`), a set of classes that implement direct image alignment of projector-camera systems (mainly `GNImageAligner`, `ProjectiveTransformer`, `ProjectiveColorTransformer`, `ProCamTransformer`, and `ReflectanceInitializer`), as well as miscellaneous functionality in the `JavaCV` class. Some of these classes also have an OpenCL and OpenGL counterpart, their names ending with `CL`, i.e.: `JavaCVCL`, etc. except for `GLCanvasFrame`.
JavaCV also comes with hardware accelerated full-screen image display (`CanvasFrame` and `GLCanvasFrame`), easy-to-use methods to execute code in parallel on multiple cores (`Parallel`), user-friendly geometric and color calibration of cameras and projectors (`GeometricCalibrator`, `ProCamGeometricCalibrator`, `ProCamColorCalibrator`), detection and matching of feature points (`ObjectFinder`), a set of classes that implement direct image alignment of projector-camera systems (mainly `GNImageAligner`, `ProjectiveTransformer`, `ProjectiveColorTransformer`, `ProCamTransformer`, and `ReflectanceInitializer`), a blob analysis package (`Blobs`), as well as miscellaneous functionality in the `JavaCV` class. Some of these classes also have an OpenCL and OpenGL counterpart, their names ending with `CL` or starting with `GL`, i.e.: `JavaCVCL`, `GLCanvasFrame`, etc.

To learn how to use the API, since documentation currently lacks, please refer to the [#Quick_Start_for_OpenCV_and_FFmpeg] section below as well as the [http://code.google.com/p/javacv/source/browse/samples/ sample programs], including one for Android, also found in the `samples` directory. You may also find it useful to refer to the source code of [http://code.google.com/p/javacv/source/browse?repo=procamcalib ProCamCalib] and [http://code.google.com/p/javacv/source/browse?repo=procamtracker ProCamTracker] as well as [http://code.google.com/p/javacv/source/browse?repo=examples Examples ported from OpenCV2 Cookbook] and the associated [http://code.google.com/p/javacv/wiki/OpenCV2_Cookbook_Examples Wiki pages].

Expand Down Expand Up @@ -217,12 +217,13 @@ This project was conceived at the Okutomi & Tanaka Laboratory, Tokyo Institute o


==Changes==
* Included new `Blobs` module from David Grossman and the corresponding `BlobDemo` sample
* Added missing `opencv_core.partition()` function (issue #144)
* Fixed up the samples a bit (issue #229 and issue #230)
* Switched the majority of `@Adapter` annotations to more concise ones like `@StdVector` as allowed by new capabilities of JavaCPP
* Fixed `FFmpegFrameGrabber.getLengthInFrames()` and `OpenCVFrameGrabber.getLengthInTime()` (issue #231 and issue #236)
* Enhanced `FFmpegFrameRecorder` to support conversion between audio sample formats (for the experimental AAC encoder among other things) and to let two different threads call `record(samples)` and `record(image)` simultaneously, plus a couple of other features like `setFrameNumber()`, which lets users skip image frames
* Added a `javacpp.skip` property to `pom.xml`, such that a command like `mvn package -Pall -Djavacpp.skip=true` only recompiles the Java source files, but also added `platform.root` and `compiler.path`, which map directly to JavaCPP's for convenience
* Added a `javacpp.skip` property to `pom.xml`, such that a command like `mvn package -Pall -Djavacpp.skip=true` only recompiles the Java source files, but also added `platform.root` and `compiler.path` properties, which map directly to JavaCPP's for convenience

===July 21, 2012 version 0.2===
* Provided new `javacv-linux-arm.jar` build thanks to Jeremy Nicola (issue #184)
Expand Down
Binary file added samples/BlackBalls.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added samples/Blob1.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added samples/Blob2.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added samples/Blob3.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
269 changes: 269 additions & 0 deletions samples/BlobDemo.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,269 @@
import com.googlecode.javacv.Blobs;
import com.googlecode.javacv.CanvasFrame;

import static com.googlecode.javacv.cpp.opencv_core.*;
import static com.googlecode.javacv.cpp.opencv_highgui.*;
import static com.googlecode.javacv.cpp.opencv_imgproc.*;

///////////////////////////////////////////////////////////////////
//* *//
//* As the author of this code, I place all of this code into *//
//* the public domain. Users can use it for any legal purpose. *//
//* *//
//* - Dave Grossman *//
//* *//
///////////////////////////////////////////////////////////////////
public class BlobDemo
{
public static void main(String[] args)
{
System.out.println("STARTING...\n");
demo();
System.out.println("ALL DONE");
}

public static void demo()
{
int MinArea = 6;
int ErodeCount =0;
int DilateCount = 0;

IplImage RawImage = null;

// Read an image.
for(int k = 0; k < 7; k++)
{
if(k == 0) { RawImage = cvLoadImage("Images/BlackBalls.jpg"); MinArea = 250; ErodeCount = 0; DilateCount = 1; }
else if(k == 1) { RawImage = cvLoadImage("Images/Shapes1.jpg"); MinArea = 6; ErodeCount = 0; DilateCount = 1; }
else if(k == 2) { RawImage = cvLoadImage("Images/Shapes2.jpg"); MinArea = 250; ErodeCount = 0; DilateCount = 1; }
else if(k == 3) { RawImage = cvLoadImage("Images/Blob1.jpg"); MinArea = 2800; ErodeCount = 1; DilateCount = 1; }
else if(k == 4) { RawImage = cvLoadImage("Images/Blob2.jpg"); MinArea = 2800; ErodeCount = 1; DilateCount = 1; }
else if(k == 5) { RawImage = cvLoadImage("Images/Blob3.jpg"); MinArea = 2800; ErodeCount = 1; DilateCount = 1; }
else if(k == 6) { RawImage = cvLoadImage("Images/Rice.jpg"); MinArea = 30; ErodeCount = 2; DilateCount = 1; }
//ShowImage(RawImage, "RawImage", 512);

IplImage GrayImage = cvCreateImage(cvGetSize(RawImage), IPL_DEPTH_8U, 1);
cvCvtColor(RawImage, GrayImage, CV_BGR2GRAY);
//ShowImage(GrayImage, "GrayImage", 512);

IplImage BWImage = cvCreateImage(cvGetSize(GrayImage), IPL_DEPTH_8U, 1);
cvThreshold(GrayImage, BWImage, 127, 255, CV_THRESH_BINARY);
//ShowImage(BWImage, "BWImage");

IplImage WorkingImage = cvCreateImage(cvGetSize(BWImage), IPL_DEPTH_8U, 1);
cvErode(BWImage, WorkingImage, null, ErodeCount);
cvDilate(WorkingImage, WorkingImage, null, DilateCount);
//ShowImage(WorkingImage, "WorkingImage", 512);

//cvSaveImage("Images/Working.jpg", WorkingImage);
//PrintGrayImage(WorkingImage, "WorkingImage");
//BinaryHistogram(WorkingImage);

Blobs Regions = new Blobs();
Regions.BlobAnalysis(
WorkingImage, // image
-1, -1, // ROI start col, row
-1, -1, // ROI cols, rows
1, // border (0 = black; 1 = white)
MinArea); // minarea
Regions.PrintRegionData();

for(int i = 1; i <= Blobs.MaxLabel; i++)
{
double [] Region = Regions.RegionData[i];
int Parent = (int) Region[Blobs.BLOBPARENT];
int Color = (int) Region[Blobs.BLOBCOLOR];
int MinX = (int) Region[Blobs.BLOBMINX];
int MaxX = (int) Region[Blobs.BLOBMAXX];
int MinY = (int) Region[Blobs.BLOBMINY];
int MaxY = (int) Region[Blobs.BLOBMAXY];
Highlight(RawImage, MinX, MinY, MaxX, MaxY, 1);
}

ShowImage(RawImage, "RawImage", 512);

cvReleaseImage(GrayImage); GrayImage = null;
cvReleaseImage(BWImage); BWImage = null;
cvReleaseImage(WorkingImage); WorkingImage = null;
}
cvReleaseImage(RawImage); RawImage = null;
}

// Versions with 2, 3, and 4 parms respectively
public static void ShowImage(IplImage image, String caption)
{
CvMat mat = image.asCvMat();
int width = mat.cols(); if(width < 1) width = 1;
int height = mat.rows(); if(height < 1) height = 1;
double aspect = 1.0 * width / height;
if(height < 128) { height = 128; width = (int) ( height * aspect ); }
if(width < 128) width = 128;
height = (int) ( width / aspect );
ShowImage(image, caption, width, height);
}
public static void ShowImage(IplImage image, String caption, int size)
{
if(size < 128) size = 128;
CvMat mat = image.asCvMat();
int width = mat.cols(); if(width < 1) width = 1;
int height = mat.rows(); if(height < 1) height = 1;
double aspect = 1.0 * width / height;
if(height != size) { height = size; width = (int) ( height * aspect ); }
if(width != size) width = size;
height = (int) ( width / aspect );
ShowImage(image, caption, width, height);
}
public static void ShowImage(IplImage image, String caption, int width, int height)
{
CanvasFrame canvas = new CanvasFrame(caption, 1); // gamma=1
canvas.setDefaultCloseOperation(javax.swing.JFrame.EXIT_ON_CLOSE);
canvas.setCanvasSize(width, height);
canvas.showImage(image);
}

public static void Highlight(IplImage image, int [] inVec)
{
Highlight(image, inVec[0], inVec[1], inVec[2], inVec[3], 1);
}
public static void Highlight(IplImage image, int [] inVec, int Thick)
{
Highlight(image, inVec[0], inVec[1], inVec[2], inVec[3], Thick);
}
public static void Highlight(IplImage image, int xMin, int yMin, int xMax, int yMax)
{
Highlight(image, xMin, yMin, xMax, yMax, 1);
}
public static void Highlight(IplImage image, int xMin, int yMin, int xMax, int yMax, int Thick)
{
CvPoint pt1 = cvPoint(xMin,yMin);
CvPoint pt2 = cvPoint(xMax,yMax);
CvScalar color = cvScalar(255,0,0,0); // blue [green] [red]
cvRectangle(image, pt1, pt2, color, Thick, 4, 0);
}

public static void PrintGrayImage(IplImage image, String caption)
{
int size = 512; // impractical to print anything larger
CvMat mat = image.asCvMat();
int cols = mat.cols(); if(cols < 1) cols = 1;
int rows = mat.rows(); if(rows < 1) rows = 1;
double aspect = 1.0 * cols / rows;
if(rows > size) { rows = size; cols = (int) ( rows * aspect ); }
if(cols > size) cols = size;
rows = (int) ( cols / aspect );
PrintGrayImage(image, caption, 0, cols, 0, rows);
}
public static void PrintGrayImage(IplImage image, String caption, int MinX, int MaxX, int MinY, int MaxY)
{
int size = 512; // impractical to print anything larger
CvMat mat = image.asCvMat();
int cols = mat.cols(); if(cols < 1) cols = 1;
int rows = mat.rows(); if(rows < 1) rows = 1;

if(MinX < 0) MinX = 0; if(MinX > cols) MinX = cols;
if(MaxX < 0) MaxX = 0; if(MaxX > cols) MaxX = cols;
if(MinY < 0) MinY = 0; if(MinY > rows) MinY = rows;
if(MaxY < 0) MaxY = 0; if(MaxY > rows) MaxY = rows;

System.out.println("\n" + caption);
System.out.print(" +");
for(int icol = MinX; icol < MaxX; icol++) System.out.print("-");
System.out.println("+");

for(int irow = MinY; irow < MaxY; irow++)
{
if(irow<10) System.out.print(" ");
if(irow<100) System.out.print(" ");
System.out.print(irow);
System.out.print("|");
for(int icol = MinX; icol < MaxX; icol++)
{
int val = (int) mat.get(irow,icol);
String C = " ";
if(val == 0) C = "*";
System.out.print(C);
}
System.out.println("|");
}
System.out.print(" +");
for(int icol = MinX; icol < MaxX; icol++) System.out.print("-");
System.out.println("+");
}

public static void PrintImageProperties(IplImage image)
{
CvMat mat = image.asCvMat();
int cols = mat.cols();
int rows = mat.rows();
int depth = mat.depth();
System.out.println("ImageProperties for " + image + " : cols=" + cols + " rows=" + rows + " depth=" + depth);
}

public static float BinaryHistogram(IplImage image)
{
CvScalar Sum = cvSum(image);
float WhitePixels = (float) ( Sum.getVal(0) / 255 );
CvMat mat = image.asCvMat();
float TotalPixels = mat.cols() * mat.rows();
//float BlackPixels = TotalPixels - WhitePixels;
return ((float) WhitePixels) / TotalPixels;
}

// Counterclockwise small angle rotation by skewing - Does not stretch border pixels
public static IplImage SkewGrayImage(IplImage Src, double angle) // angle is in radians
{
//double radians = - Math.PI * angle / 360.0; // Half because skew is horizontal and vertical
double sin = - Math.sin(angle);
double AbsSin = Math.abs(sin);

int nChannels = Src.nChannels();
if(nChannels != 1)
{
System.out.println("ERROR: SkewGrayImage: Require 1 channel: nChannels=" + nChannels);
System.exit(1);
}

CvMat SrcMat = Src.asCvMat();
int SrcCols = SrcMat.cols();
int SrcRows = SrcMat.rows();

double WidthSkew = AbsSin * SrcRows;
double HeightSkew = AbsSin * SrcCols;

int DstCols = (int) ( SrcCols + WidthSkew );
int DstRows = (int) ( SrcRows + HeightSkew );

CvMat DstMat = cvCreateMat(DstRows, DstCols, CV_8UC1); // Type matches IPL_DEPTH_8U
cvSetZero(DstMat);
cvNot(DstMat, DstMat);

for(int irow = 0; irow < DstRows; irow++)
{
int dcol = (int) ( WidthSkew * irow / SrcRows );
for(int icol = 0; icol < DstCols; icol++)
{
int drow = (int) ( HeightSkew - HeightSkew * icol / SrcCols );
int jrow = irow - drow;
int jcol = icol - dcol;
if(jrow < 0 || jcol < 0 || jrow >= SrcRows || jcol >= SrcCols) DstMat.put(irow, icol, 255);
else DstMat.put(irow, icol, (int) SrcMat.get(jrow,jcol));
}
}

IplImage Dst = cvCreateImage(cvSize(DstCols, DstRows), IPL_DEPTH_8U, 1);
Dst = DstMat.asIplImage();
return Dst;
}

public static IplImage TransposeImage(IplImage SrcImage)
{
CvMat mat = SrcImage.asCvMat();
int cols = mat.cols();
int rows = mat.rows();
IplImage DstImage = cvCreateImage(cvSize(rows, cols), IPL_DEPTH_8U, 1);
cvTranspose(SrcImage, DstImage);
cvFlip(DstImage,DstImage,1);
return DstImage;
}
}

Binary file added samples/Rice.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added samples/Shapes1.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added samples/Shapes2.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit 0bd7962

Please sign in to comment.