OpenCV中文网站

 找回密码
 立即注册
搜索
热搜: 安装 配置
查看: 71366|回复: 85

Java+Opencv 入门汇总

[复制链接]
发表于 2016-3-11 10:41:28 | 显示全部楼层 |阅读模式
本帖最后由 流放荒帝 于 2016-4-14 10:00 编辑

兄弟最近在收集一些java +opencv 入门知识点,希望广大战友给及一些支持。不胜感激,谢谢!!!
以下是我找到的一个OpenCV的Java教程文档!链接
http://opencv-java-tutorials.readthedocs.org/en/latest/

类似以下这样的知识点,可以留言,也可以发到邮箱15978772015@163.com

Mat img=Highgui.imread(路径); //读图像
Highi.imwrite(路径,img);//写图像

Mat img2=new Mat();
Imgproc.blur(img,img2,new Size(3,3));//光滑处理

Imgproc.cvtColor(img,img2, Imgproc.COLOR_BGR2GRAY);//RGB==>Gray
Imgproc.equalizeHist(GrayImg,GrayImg);  //直方图均衡化
                        
List<Mat> images = new ArrayList<Mat>();
Core.split(img, images);//RGB通道分离
Mat mat=images.get(2);//获得第二通道分量
Core.merge(images,img);//RGB通道合并

回复

使用道具 举报

 楼主| 发表于 2016-3-24 14:48:03 | 显示全部楼层

Canny 边缘检测

本帖最后由 流放荒帝 于 2016-4-14 14:28 编辑

                 /**
         * Apply Canny
         *
         * @param frame
         *            the current frame
         * @return an image elaborated with Canny
         */
        private Mat doCanny(Mat frame)
        {
                // init
                Mat grayImage = new Mat();
                Mat detectedEdges = new Mat();
               
                // convert to grayscale
                Imgproc.cvtColor(frame, grayImage, Imgproc.COLOR_BGR2GRAY);
               
                // reduce noise with a 3x3 kernel
                Imgproc.blur(grayImage, detectedEdges, new Size(3, 3));
               
                // canny detector, with ratio of lower:upper threshold of 3:1
                Imgproc.Canny(detectedEdges, detectedEdges, this.threshold.getValue(), this.threshold.getValue() * 3);
               
                // using Canny's output as a mask, display the result
                Mat dest = new Mat();
                frame.copyTo(dest, detectedEdges);
               
                return dest;
        }
边缘检测.png
回复 支持 1 反对 0

使用道具 举报

 楼主| 发表于 2016-3-24 14:39:30 | 显示全部楼层

背景去除 简单案列,只适合背景单一的图像

本帖最后由 流放荒帝 于 2016-4-21 09:57 编辑

                         private Mat doBackgroundRemoval(Mat frame)
     {
             // init
             Mat hsvImg = new Mat();
             List<Mat> hsvPlanes = new ArrayList<>();
             Mat thresholdImg = new Mat();

             int thresh_type = Imgproc.THRESH_BINARY_INV;

             // threshold the image with the average hue value
             hsvImg.create(frame.size(), CvType.CV_8U);
             Imgproc.cvtColor(frame, hsvImg, Imgproc.COLOR_BGR2HSV);
             Core.split(hsvImg, hsvPlanes);

             // get the average hue value of the image

            Scalar average=Core.mean(hsvPlanes.get(0));
            double threshValue =average.val[0];
             Imgproc.threshold(hsvPlanes.get(0), thresholdImg, threshValue, 179.0, thresh_type);

             Imgproc.blur(thresholdImg, thresholdImg, new Size(5, 5));

             // dilate to fill gaps, erode to smooth edges
             Imgproc.dilate(thresholdImg, thresholdImg, new Mat(), new Point(-1, -1), 1);
             Imgproc.erode(thresholdImg, thresholdImg, new Mat(), new Point(-1, -1), 3);

             Imgproc.threshold(thresholdImg, thresholdImg, threshValue, 179.0, Imgproc.THRESH_BINARY);

             // create the new image
             Mat foreground = new Mat(frame.size(), CvType.CV_8UC3, new Scalar(255, 255, 255));
             thresholdImg.convertTo(thresholdImg,CvType.CV_8U);
             frame.copyTo(foreground, thresholdImg);//掩膜图像复制

             return foreground;
     }
      

背景去除

背景去除

点评

zlg
我想做一个人脸识别,识别出脸部,眼睛和鼻子,  发表于 2016-9-18 16:45
回复 支持 0 反对 1

使用道具 举报

 楼主| 发表于 2016-3-12 13:39:19 | 显示全部楼层

人脸检测

本帖最后由 流放荒帝 于 2016-4-14 10:37 编辑

Mat img=读入图像
Rect Roi=new Rect(new Point(5,5),new Size(400,800));

Mat image= img.submat(Roi);//子图

String xmlfilePath = "haarcascade_frontalface_alt2.xml";
MatOfRect faceDetections = new MatOfRect();
CascadeClassifier faceDetector = new CascadeClassifier(xmlfilePath);
faceDetector.detectMultiScale(image , faceDetections, 1.1,2,0|Objdetect.CASCADE_FIND_BIGGEST_OBJECT, new Size( ), new Size());
faceCascade.detectMultiScale(image, faces, 1.1, 2, 0 | Objdetect.CASCADE_SCALE_IMAGE, new Size(), new Size());
  • image Matrix of the type CV_8U containing an image where objects are detected.
  • objects Vector of rectangles where each rectangle contains the detected object.包含人脸的矩形vector
  • scaleFactor Parameter specifying how much the image size is reduced at each image scale.看不懂默认1.1
  • minNeighbors Parameter specifying how many neighbors each candidate rectangle should have to retain it.
  • flags Parameter with the same meaning for an old cascade as in the function cvHaarDetectObjects. It is not used for a new cascade.//Objdetect.CASCADE_FIND_BIGGEST_OBJECT  找最大的人脸目标,一次只获得一个人脸
  • minSize Minimum possible object size. Objects smaller than that are ignored.//脸部区域最小下限
  • maxSize Maximum possible object size. Objects larger than that are ignored.//脸部区域最大上限


以下是人脸检测小函数
   
private void detectAndDisplay(Mat frame)
   {
           MatOfRect faces = new MatOfRect();
           Mat grayFrame = new Mat();
       // convert the frame in gray scale
           Imgproc.cvtColor(frame, grayFrame, Imgproc.COLOR_BGR2GRAY);
      //  equalize the frame histogram to  improve the result
          Imgproc.equalizeHist(grayFrame, grayFrame);
     //  compute minimum face size (20%  of the frame height, in our case)
         int absoluteFaceSize = Math.round(height * 0.2f);
    //  detect faces
         faceCascade.detectMultiScale(grayFrame,  faces, 1.1, 2, 0 | Objdetect.CASCADE_SCALE_IMAGE, new Size(absoluteFaceSize, absoluteFaceSize), new Size());
   //  each rectangle in faces is a  face: draw them!
       Rect[] facesArray = faces.toArray();
       for (int i = 0; i < facesArray.length; i++)
     {
            Imgproc.rectangle(frame, facesArray.tl(), facesArray.br(), new Scalar(0, 255, 0), 3);
     }
}



回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-3-12 13:40:02 | 显示全部楼层
7862632 发表于 2016-3-11 11:45
用jni更简单,直接移植现成的代码就行,而且还不用装opencv

问题是,上面要求这么干,没有办法
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-3-24 16:30:07 | 显示全部楼层
本帖最后由 流放荒帝 于 2016-3-24 16:36 编辑

Mat blurredImage = new Mat();
Mat hsvImage = new Mat();
Mat mask = new Mat();
Mat morphOutput = new Mat();

// remove some noise
Imgproc.blur(frame, blurredImage, new Size(7, 7));//去噪

// convert the frame to HSV
Imgproc.cvtColor(blurredImage, hsvImage, Imgproc.COLOR_BGR2HSV);


/**
         * Given a binary image containing one or more closed surfaces, use it as a
         * mask to find and highlight the objects contours
         *
         * @param maskedImage
         *            the binary image to be used as a mask
         * @param frame
         *            the original {@link Mat} image to be used for drawing the
         *            objects contours
         * @return the {@link Mat} image with the objects contours framed
         */


private Mat findAndDrawBalls(Mat maskedImage, Mat frame)
{
         // init
        List<MatOfPoint> contours = new ArrayList<>();
        Mat hierarchy = new Mat();

        // find contours
        Imgproc.findContours(maskedImage, contours, hierarchy, Imgproc.RETR_CCOMP, Imgproc.CHAIN_APPROX_SIMPLE);

        // if any contour exist...
        if (hierarchy.size().height > 0 && hierarchy.size().width > 0)
        {
        // for each contour, display it in blue
                for (int idx = 0; idx >= 0; idx = (int) hierarchy.get(0, idx)[0])
                {
                        Imgproc.drawContours(frame, contours, idx, new Scalar(250, 0, 0));
                }
        }
        return frame;
}

Mat blurredImage = new Mat();
Mat hsvImage = new Mat();
Mat mask = new Mat();
Mat morphOutput = new Mat();
                        
// remove some noise
Imgproc.blur(frame, blurredImage, new Size(7, 7));

// convert the frame to HSV
Imgproc.cvtColor(blurredImage, hsvImage, Imgproc.COLOR_BGR2HSV);
                        
// get thresholding values from the UI
// remember: H ranges 0-180, S and V range 0-255
Scalar minValues = new Scalar(this.hueStart.getValue(), this.saturationStart.getValue(),
this.valueStart.getValue());
Scalar maxValues = new Scalar(this.hueStop.getValue(), this.saturationStop.getValue(),
this.valueStop.getValue());
                                       
// show the current selected HSV range
String valuesToPrint = "Hue range: " + minValues.val[0] + "-" + maxValues.val[0]
+ "\tSaturation range: " + minValues.val[1] + "-" + maxValues.val[1] + "\tValue range: "
+ minValues.val[2] + "-" + maxValues.val[2];
this.onFXThread(this.hsvValuesProp, valuesToPrint);

                                        // threshold HSV image to select tennis balls
Core.inRange(hsvImage, minValues, maxValues, mask);
                                        // show the partial output
this.onFXThread(this.maskImage.imageProperty(), this.mat2Image(mask));

                                        // morphological operators
                                        // dilate with large element, erode with small ones
Mat dilateElement = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(24, 24));
Mat erodeElement = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(12, 12));

Imgproc.erode(mask, morphOutput, erodeElement);
Imgproc.erode(mask, morphOutput, erodeElement);//腐蚀
               
Imgproc.dilate(mask, morphOutput, dilateElement);
Imgproc.dilate(mask, morphOutput, dilateElement);//膨胀

// show the partial output
this.onFXThread(this.morphImage.imageProperty(), this.mat2Image(morphOutput));

// find the tennis ball(s) contours and show them
frame = this.findAndDrawBalls(morphOutput, frame);
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-3-31 09:56:48 | 显示全部楼层

直方图 opencv c++ VS java 版本对比

本帖最后由 流放荒帝 于 2016-3-31 13:19 编辑

C++:  void calcHist(vector_Mat images, vector_int channels, Mat mask, Mat& hist, vector_int histSize, vector_float ranges, bool accumulate = false)
          void calcHist( InputArrayOfArrays images, const vector<int>& channels,InputArray mask, OutputArray hist,const vector<int>& histSize,const                 vector<float>& ranges,bool accumulate=false );
java:void calcHist(List<Mat> images, MatOfInt channels, Mat mask, Mat hist, MatOfInt histSize, MatOfFloat ranges, boolean accumulate)
//蓝绿色字体是java版本的
Mat src, dst;

// 装载图像
Mat src = imread( "文件路径" );
Mat frame= Imgproc.imread( "文件路径" );

/// 分割成3个单通道图像 ( R, G 和 B )
vector<Mat> rgb_planes;
split(src, rgb_planes );
//List<Mat> images = new ArrayList<Mat>();
//Core.split(frame, images);

/// 设定bin数目
int histSize = 255;

/// 设定取值范围 ( R,G,B) )
float range[] = { 0, 255 } ;
const float* histRange = { range };

//MatOfInt histSize = new MatOfInt(256);
//MatOfFloat histRange = new MatOfFloat(0, 256);
//MatOfInt channels = new MatOfInt(0);

bool uniform = true; bool accumulate = false;

Mat r_hist,g_hist, b_hist;
//Mat hist_b = new Mat();
//Mat hist_g = new Mat();
//Mat hist_r = new Mat();

/// 计算直方图:
                 calcHist(&rgb_planes[0], 1,        0,           Mat(),    r_hist, 1, &histSize, &histRange, uniform, accumulate );
                 calcHist(&rgb_planes[1], 1,        0,           Mat(),    g_hist, 1, &histSize, &histRange, uniform, accumulate );
                 calcHist(&rgb_planes[2], 1,        0,           Mat(),    b_hist, 1, &histSize, &histRange, uniform, accumulate );
//Imgproc.calcHist(images.subList(0, 1), channels, new Mat(), hist_b    , histSize,  histRange, false);
//Imgproc.calcHist(images.subList(1, 2), channels, new Mat(), hist_g    , histSize,  histRange, false);
//Imgproc.calcHist(images.subList(2, 3), channels, new Mat(), hist_r     , histSize,  histRange, false);

// 创建直方图画布
int hist_w = 400;
int hist_h = 400;
int bin_w = cvRound( (double) hist_w/histSize );
//int hist_w = 400; // width of the histogram image
//int hist_h = 400; // height of the histogram image
//int bin_w = (int) Math.round(hist_w / histSize.get(0, 0)[0]);


Mat histImage(hist_w, hist_h, CV_8UC3, Scalar( 0,0,0) );
//Mat histImage = new Mat(hist_h, hist_w, CvType.CV_8UC3, new Scalar(0, 0, 0));

/// 将直方图归一化到范围 [ 0, histImage.rows ]
normalize(r_hist,r_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat() );
normalize(g_hist,g_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat() );
normalize(b_hist,b_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat() );
//Core.normalize(hist_b, hist_b, 0, histImage.rows(), Core.NORM_MINMAX, -1, new Mat());
//Core.normalize(hist_g, hist_g, 0, histImage.rows(), Core.NORM_MINMAX, -1, new Mat());
//Core.normalize(hist_r, hist_r, 0, histImage.rows(), Core.NORM_MINMAX, -1, new Mat());


/// 在直方图画布上画出直方图
for( int i = 1; i < histSize; i++ )
   {
     line(histImage, Point( bin_w*(i-1), hist_h - cvRound(r_hist.at<float>(i-1)) ) ,
                      Point( bin_w*(i), hist_h - cvRound(r_hist.at<float>(i)) ),
                      Scalar( 0, 0, 255), 2, 8, 0  );
     line(histImage, Point( bin_w*(i-1), hist_h - cvRound(g_hist.at<float>(i-1)) ) ,
                      Point( bin_w*(i), hist_h - cvRound(g_hist.at<float>(i)) ),
                      Scalar( 0, 255, 0), 2, 8, 0  );
     line( histImage, Point( bin_w*(i-1), hist_h - cvRound(b_hist.at<float>(i-1)) ) ,
                      Point( bin_w*(i), hist_h - cvRound(b_hist.at<float>(i)) ),
                      Scalar( 255, 0, 0), 2, 8, 0  );
    }
// effectively draw the histogram(s)
for (int i = 1; i < histSize.get(0, 0)[0]; i++)
{
// B component or gray image
Imgproc.line(histImage, new Point(bin_w * (i - 1), hist_h - Math.round(hist_b.get(i - 1, 0)[0])),
new Point(bin_w * (i), hist_h - Math.round(hist_b.get(i, 0)[0])), new Scalar(255, 0, 0), 2, 8, 0);
// G and R components (if the image is not in gray scale)
Imgproc.line(histImage, new Point(bin_w * (i - 1), hist_h - Math.round(hist_g.get(i - 1, 0)[0])),
new Point(bin_w * (i), hist_h - Math.round(hist_g.get(i, 0)[0])), new Scalar(0, 255, 0), 2, 8,0);
Imgproc.line(histImage, new Point(bin_w * (i - 1), hist_h - Math.round(hist_r.get(i - 1, 0)[0])),
new Point(bin_w * (i), hist_h - Math.round(hist_r.get(i, 0)[0])), new Scalar(0, 0, 255), 2, 8,0);
}

Image histImg = mat2Image(histImage);




/// 显示直方图
namedWindow("calcHist Demo", CV_WINDOW_AUTOSIZE );
imshow("calcHist Demo", histImage );

waitKey(0);

return 0;

}
private Image mat2Image(Mat frame)
{
// create a temporary buffer
MatOfByte buffer = new MatOfByte();
// encode the frame in the buffer, according to the PNG format
Imgcodecs.imencode(".png", frame, buffer);
// build and return an Image created from the image encoded in the  buffer
return new Image(new ByteArrayInputStream(buffer.toArray()));
}


回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-5-24 15:24:24 | 显示全部楼层

GrabCut 函数应用 人脸皮肤抓取

本帖最后由 流放荒帝 于 2016-5-24 15:51 编辑

                           GC_BGD = 0,
                           GC_FGD = 1,
                           GC_PR_BGD = 2,
                           GC_PR_FGD = 3,
                           GC_INIT_WITH_RECT = 0,
                           GC_INIT_WITH_MASK = 1,

                           GC_BGD defines an obvious background pixels.
                           GC_FGD defines an obvious foreground (object) pixel.
                           GC_PR_BGD defines a possible background pixel.
                           GC_PR_FGD defines a possible foreground pixel.


                            Mat bgdModel=new Mat();//暂时没用
                            Mat fgdModel=new Mat();//暂时没用
                            Mat grabSkin=new Mat(orgBGRImageSmall.size(),CvType.CV_8U);

                            float a2=160*160;
                            float b2=115*115;
                            byte ellipseMask[]=new byte[smallWidth*smallHeight];
                            for (int i = 0; i <smallHeight; i++)
                            {
                                   for (int j = 0; j <smallWidth; j++)
                                   {
                                         if (((i-170)*(i-170)/a2+(j-120)*(j-120)/b2)<1) {
                                                  ellipseMask[i*smallWidth+j]=(byte)3;//==3才是前景图像也就是皮肤区域
                                           }
                                   }
                           }
                           grabSkin.put(0,0,ellipseMask);//椭圆 掩膜 可能会有皮肤的区域Mask
                           Imgproc.grabCut(orgBGRImageSmall,grabSkin,rectOfSmallFace,bgdModel,fgdModel,3,Imgproc.GC_INIT_WITH_MASK);
                           Scalar aaScalar=new Scalar(3);
                           Mat grabSkinTmp0=new Mat();
                            Core.compare(maskSkin,aaScalar,grabSkinTmp0,Core.CMP_EQ);


原图

原图
GrabSkin.jpg
回复 支持 反对

使用道具 举报

发表于 2016-7-15 14:49:22 | 显示全部楼层
你好楼主 请问你的canny边缘检测的大小阙值是怎么计算的?方便告知一下吗?急求
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-7-15 17:12:47 | 显示全部楼层
shaoyi7 发表于 2016-7-15 14:49
你好楼主 请问你的canny边缘检测的大小阙值是怎么计算的?方便告知一下吗?急求 ...

找几个值带入,试出来的,没有什么公式和经验
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|OpenCV中文网站

GMT+8, 2024-5-7 08:16 , Processed in 0.013342 second(s), 20 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表