JavaCV是OpenCV的Wrapper,通过JNI调用OpenCV,按理说JavaCV和OpenCV应该是等价的,但是JavaCV并不像最近比较新的使用python调用OpenCV那么完善,没有例子,没有API文档,在使用中间会遇到各种问题,特以此文来记录自己遇到的问题和如何解决。

1. 如何新建一个JavaCV的Maven工程

在pom.xml中加入:

标签<repostiories>中加入javacv的远程仓库地址:

<repository>
   <id>javacv repo</id>
   <url> http://maven2.javacv.googlecode.com/git/</url>
</repository>

标签<dependencies>中加入javacv的相关依赖:

<dependency>
    <groupId>com.googlecode.javacv</groupId>
    <artifactId>javacv</artifactId>
    <version>0.6</version>
</dependency>
<dependency>
    <groupId>com.googlecode.javacv</groupId>
    <artifactId>javacv</artifactId>
    <classifier>macosx-x86_64</classifier>
    <version>0.6</version>
</dependency>

2. 如何改写OpenCV程序为JavaCV程序

请参考https://code.google.com/p/javacv/wiki/ConvertingOpenCV,然后再进行JavaCV程序的编写。

3. 使用JavaCV进行人员检测

本程序参考了python版本的OpenCV人员检测范例peopledetect.py.(╮(╯▽╰)╭ 爱python一辈子)

程序的基本逻辑是使用HOG进行人员检测,有两点比较tricky:

(1) 使用HOG检测会得到很多矩形,我们只想要最外面的矩形,即如果矩形A不在其他所有的矩形中,不被所有其他矩形所包含,我们就认为这个矩形是我们想要的。

(2) HOG一般返回的矩形都比实际的物体要大,所以我们收缩了矩形,使得它圈人圈的更精确。

下面是我的代码:

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

import java.awt.event.KeyEvent;

import org.junit.Test;

import com.googlecode.javacv.CanvasFrame;
import com.googlecode.javacv.cpp.opencv_objdetect.HOGDescriptor;


public class PeopleDetectInImage {

    //如果r在q中则返回true,否则返回false
    public boolean inside(CvRect r, CvRect q){
        int rx = r.x(), ry = r.y(), rw = r.width(), rh = r.height();
        int qx = q.x(), qy = q.y(), qw = q.width(), qh = q.height();
        return (rx > qx) && (ry > qy) && ((rx + rw) < (qx + qw)) && ((ry + rh) < (qy + qh));
    }

    //由于HOG描述子返回的矩形都比实际的物体大一点
    // 所以我们缩小一下矩形已返回更好的结果
    public IplImage draw_detection(CvRect r, IplImage img){
        int x = r.x(), y = r.y(), w = r.width(), h = r.height();
        int pad_w = (int) (0.15*w), pad_h = (int) (0.05*h);
        cvRectangle(img, cvPoint(x+pad_w, y+pad_h),cvPoint(x+w-pad_w, y+h-pad_h), CvScalar.GREEN, 2, CV_AA, 0);
        return img;
    }

    @Test
    public void detect_peoples() throws Exception {
        CanvasFrame canvasFrame = new CanvasFrame("HOG-Test");

        HOGDescriptor hog = new HOGDescriptor();
        hog.setSVMDetector(HOGDescriptor.getDefaultPeopleDetector());

        IplImage frame = cvLoadImage("/Users/zhaoxm/InBUPT/test_pics/test.jpg");

        IplImage frame_clone = null;

        CvRect found=new CvRect();

        hog.detectMultiScale(frame, found, 0, cvSize(8,8), cvSize(32, 32), 1.05,2);

        System.out.println(found.capacity());

        //找到最外面的矩形
        for(int i=0;i<found.capacity();i++) {
            CvRect r = found.position(i);

            boolean sign = false; //true代表矩形是里面的,false代表矩形是最外面的

            for(int j=0;j<found.capacity();j++) {
                if(i != j){  //不是同一个矩形
                    CvRect q = found.position(j);
                    if(inside(r,q)){
                        System.out.println(r);
                        System.out.println(q);
                        sign = true;
                        break;
                    }
                }
                if(!sign){ //r是最外面的框框
                    frame = draw_detection(r,frame);
                    //cvRectangle(frame, cvPoint(r.x(), r.y()),cvPoint(r.x() + r.width(), r.y() + r.height()), CvScalar.GREEN, 2, CV_AA, 0);
                }
            }
        }
        cvSaveImage("/Users/zhaoxm/InBUPT/test_pics/peoples.png",frame);
         canvasFrame.showImage(frame);
         KeyEvent key = canvasFrame.waitKey(0);
         if (key != null) {
             cvReleaseImage(frame);
             canvasFrame.dispose();
         }
    }
    public static void main(String[] args) throws Exception {
        PeopleDetectInImage detector = new PeopleDetectInImage();
        detector.detect_peoples();
    }
}

程序运行结果如下: img

结果还算不错。其中最重要的函数是detectMultiScale,具体每个参数的解释见OpenCV文档:

C++: void gpu::HOGDescriptor::detectMultiScale(const GpuMat& img, vector& found_locations, double hit_threshold=0, Size win_stride=Size(), Size padding=Size(), double scale0=1.05, int group_threshold=2)¶

Parameters:

  • img – Source image. See gpu::HOGDescriptor::detect() for type limitations.
  • found_locations – Detected objects boundaries.
  • hit_threshold – Threshold for the distance between features and SVM classifying plane. See gpu::HOGDescriptor::detect() for details.
  • win_stride – Window stride. It must be a multiple of block stride.
  • padding – Mock parameter to keep the CPU interface compatibility. It must be (0,0).
  • scale0 – Coefficient of the detection window increase.
  • group_threshold – Coefficient to regulate the similarity threshold. When detected, some objects can be covered by many rectangles. 0 means not to perform grouping. See groupRectangles() .

Xuggler tutorial 1 使用xuggle进行视频操作(译+修改)

Fri 13 December 2013 by XiaomengZhao
原文网址:http://www.javacodegeeks.com/2011/02/introduction-xuggler-video-manipulation.html

随着互联网视频数量的爆发,开发者需要在他们的应用中非常频繁地操作视频数据。Xuggle为Java开发者提供的开源的库,能够解压,处理和压缩存储的视频数据和实时的现场直播的视频数据。Xuggle使用了非常强有力的FFmpeg媒体操作库,是FFPEG的Java Wrapper,使得开发能够使用Java更好的解压,修改媒体文件。

FFmpeg是一个完整的,跨平台的用来记录,转换,流式化音频和视频文件,支持多种格式。可能您不清楚你在使用它,但是其实你已经在使用了。但是,Xuggle不仅仅是提供给你使用复杂的FFmpeg的简单方法。Xuggle dev团队还在帮助优化FFmpeg。

然后我们需要安装FFmpeg。注意Xuggle自带了FFmpeg(优化过的)来避免错误的配置,所以你不需要自己手动的获取FFmpeg。但是在这个教程中,我们在使用Xuggle之前,需要使用FFmpeg测试一些操作,所以我们需要先分开安装FFmpeg。

FFmpeg下载页下载。Linux可以下载源代码然后编译(注:Linux其实也有编译好的包)。而Windows的话,可以下载编译好的二进制包,然后可以找到ffmpeg.exe执行程序。将它拷贝到特定目录 ...

read more
Fork me on GitHub