Java 开放式CV图像检测
所以我试着在一个图像周围画一个矩形。我正在使用Open CV从较大的图像中查找子图像。我是如何计算的,将模板图像(目标)和目标图像(场景)转换为HSV,得到对象的反投影,并将其与饱和的场景图像进行比较。有点管用。(如有任何改进,我将非常高兴)。基本上,我想在图像周围画一个矩形,然后将找到的矩形从场景中提取到一个垫子上。我试过几种方法,但似乎不起作用。这是我的密码。我的问题是如何从目标图像中获取子图像Java 开放式CV图像检测,java,android,opencv,image-processing,Java,Android,Opencv,Image Processing,所以我试着在一个图像周围画一个矩形。我正在使用Open CV从较大的图像中查找子图像。我是如何计算的,将模板图像(目标)和目标图像(场景)转换为HSV,得到对象的反投影,并将其与饱和的场景图像进行比较。有点管用。(如有任何改进,我将非常高兴)。基本上,我想在图像周围画一个矩形,然后将找到的矩形从场景中提取到一个垫子上。我试过几种方法,但似乎不起作用。这是我的密码。我的问题是如何从目标图像中获取子图像 public List<DMatch> subListGoodMatches(Lis
public List<DMatch> subListGoodMatches(List<DMatch> good_matches) {
Collections.sort(good_matches, (DMatch o1, DMatch o2) -> {
if (o1.distance < o2.distance) {
return -1;
}
if (o1.distance > o2.distance) {
return 1;
}
return 0;
});
if (good_matches.size() > 10) {
good_matches = good_matches.subList(0, 10);
}
return good_matches;
}
public List<Mat> calculateHistograms(Mat image) {
Imgproc.cvtColor(image, image, Imgproc.COLOR_BGR2HSV);
List<Mat> hsv_planes = new ArrayList<Mat>();
Core.split(image, hsv_planes);
MatOfInt histSize = new MatOfInt(256);
final MatOfFloat histRange = new MatOfFloat(0f, 256f);
boolean accumulate = true;
Mat h_hist = new Mat();
Mat s_hist = new Mat();
Mat v_hist = new Mat();
//Break channels
List<Mat> h_plane = new ArrayList<Mat>();
List<Mat> s_plane = new ArrayList<Mat>();
List<Mat> v_plane = new ArrayList<Mat>();
h_plane.add(hsv_planes.get(0));
s_plane.add(hsv_planes.get(1));
v_plane.add(hsv_planes.get(2));
Imgproc.calcHist(h_plane, new MatOfInt(0), new Mat(), h_hist, histSize, histRange, accumulate);
Imgproc.calcHist(s_plane, new MatOfInt(0), new Mat(), s_hist, histSize, histRange, accumulate);
Imgproc.calcHist(v_plane, new MatOfInt(0), new Mat(), v_hist, histSize, histRange, accumulate);
//Draw combined histograms
int hist_w = 512;
int hist_h = 600;
long bin_w = Math.round((double) hist_w / 256);
Mat histImage = new Mat(hist_h, hist_w, CvType.CV_8UC3, new Scalar(0, 0, 0));
Core.normalize(h_hist, h_hist, 3, histImage.rows(), Core.NORM_MINMAX, -1, new Mat());
Core.normalize(s_hist, s_hist, 3, histImage.rows(), Core.NORM_MINMAX, -1, new Mat());
Core.normalize(v_hist, v_hist, 3, histImage.rows(), Core.NORM_MINMAX, -1, new Mat());
for (int i = 1; i < 256; i++) {
Point p1 = new Point(bin_w * (i - 1), hist_h - Math.round(h_hist.get(i - 1, 0)[0]));
Point p2 = new Point(bin_w * (i), hist_h - Math.round(h_hist.get(i, 0)[0]));
Core.line(histImage, p1, p2, RED, 2, 8, 0);
Point p3 = new Point(bin_w * (i - 1), hist_h - Math.round(s_hist.get(i - 1, 0)[0]));
Point p4 = new Point(bin_w * (i), hist_h - Math.round(s_hist.get(i, 0)[0]));
Core.line(histImage, p3, p4, GREEN, 2, 8, 0);
Point p5 = new Point(bin_w * (i - 1), hist_h - Math.round(v_hist.get(i - 1, 0)[0]));
Point p6 = new Point(bin_w * (i), hist_h - Math.round(v_hist.get(i, 0)[0]));
Core.line(histImage, p5, p6, BLUE, 2, 8, 0);
}
Highgui.imwrite("img-histogram.jpg", histImage);
System.out.println("Hist size is: " + hsv_planes.size());
List<Mat> histograms = new ArrayList<Mat>();
histograms.add(h_hist);
histograms.add(s_hist);
histograms.add(v_hist);
return histograms;
}
public Mat identifyLowSat(Mat image) {
Mat hsvTargetImage = new Mat();
Imgproc.cvtColor(image, hsvTargetImage, Imgproc.COLOR_BGR2HSV);
List<Mat> hsv_planes = new ArrayList<Mat>();
Core.split(hsvTargetImage, hsv_planes);
//Get saturation channel
Mat s_hist = hsv_planes.get(1);
Imgproc.threshold(s_hist, s_hist, 65, 255, Imgproc.THRESH_BINARY);
Highgui.imwrite("img-saturation.png", s_hist);
return s_hist;
}
public Mat getBackProjOfHueTemplate(Mat image, Mat hue_histogram) {
Mat hsvTargetImage = new Mat();
Imgproc.cvtColor(image, hsvTargetImage, Imgproc.COLOR_BGR2HSV);
List<Mat> hsv_planes = new ArrayList<Mat>();
Core.split(hsvTargetImage, hsv_planes);
Mat backProj = new Mat();
final MatOfFloat range = new MatOfFloat(0f, 256f);
Imgproc.calcBackProject(hsv_planes, new MatOfInt(0), hue_histogram, backProj, range, 4);
Highgui.imwrite("img-backProj.png", backProj);
return backProj;
}
public Mat meanShift(Mat image) {
Mat map = new Mat();
Rect rect = new Rect();
TermCriteria term = new TermCriteria();
term.maxCount = 100;
term.type = TermCriteria.EPS;
term.epsilon = 0.1;
Imgproc.pyrMeanShiftFiltering(image, map, 0.5, 0.5, 5, term);
Highgui.imwrite("img-meanshift.png", map);
return map;
}
public MatOfDMatch filterMatches(Mat img1, Mat img2) {
FeatureDetector detector = FeatureDetector.create(FeatureDetector.SIFT);
DescriptorExtractor descriptor = DescriptorExtractor.create(DescriptorExtractor.BRISK);
DescriptorMatcher matcher = DescriptorMatcher.create(DescriptorMatcher.BRUTEFORCE_HAMMING);
// First photo
//Imgproc.cvtColor(img1, img1, Imgproc.COLOR_RGB2GRAY);
Mat descriptors1 = new Mat();
MatOfKeyPoint keypoints1 = new MatOfKeyPoint();
detector.detect(img1, keypoints1);
descriptor.compute(img1, keypoints1, descriptors1);
// Second photo
//Imgproc.cvtColor(img2, img2, Imgproc.COLOR_RGB2GRAY);
Mat descriptors2 = new Mat();
MatOfKeyPoint keypoints2 = new MatOfKeyPoint();
detector.detect(img2, keypoints2);
descriptor.compute(img2, keypoints2, descriptors2);
// Matching
MatOfDMatch matches = new MatOfDMatch();
MatOfDMatch filteredMatches = new MatOfDMatch();
matcher.match(descriptors1, descriptors2, matches);
List<DMatch> matchesList = matches.toList();
Double max_dist = Double.MIN_VALUE;
Double min_dist = Double.POSITIVE_INFINITY;
for (DMatch matchesList1 : matchesList) {
Double dist = (double) matchesList1.distance;
if (dist < min_dist) {
min_dist = dist;
}
if (dist > max_dist) {
max_dist = dist;
}
}
LinkedList<DMatch> good_matches = new LinkedList<DMatch>();
for (DMatch matchesList1 : matchesList) {
if (matchesList1.distance <= (1.5 * min_dist)) {
good_matches.addLast(matchesList1);
}
}
MatOfDMatch goodMatches = new MatOfDMatch();
//goodMatches.fromList(good_matches);
List<DMatch> newGood_Matches = subListGoodMatches(good_matches);
goodMatches.fromList(newGood_Matches);
//put keypoints mats into lists
List<KeyPoint> keypoints1_List = keypoints1.toList();
List<KeyPoint> keypoints2_List = keypoints2.toList();
//put keypoints into point2f mats so calib3d can use them to find homography
LinkedList<Point> objList = new LinkedList<Point>();
LinkedList<Point> sceneList = new LinkedList<Point>();
for (int i = 0; i < newGood_Matches.size(); i++) {
objList.addLast(keypoints2_List.get(newGood_Matches.get(i).trainIdx).pt);
sceneList.addLast(keypoints1_List.get(newGood_Matches.get(i).queryIdx).pt);
}
MatOfPoint2f obj = new MatOfPoint2f();
MatOfPoint2f scene = new MatOfPoint2f();
obj.fromList(objList);
scene.fromList(sceneList);
System.out.println(matches.size() + " " + goodMatches.size());
//output image
Mat outputImg = new Mat();
MatOfByte drawnMatches = new MatOfByte();
Features2d.drawMatches(img1, keypoints1, img2, keypoints2, goodMatches, outputImg, Scalar.all(-1), Scalar.all(-1), drawnMatches, Features2d.NOT_DRAW_SINGLE_POINTS);
Highgui.imwrite("img-matches.png", outputImg);
drawWithRect(img1, img2, obj, scene, outputImg);
keypointers1 = keypoints1;
keypointers2 = keypoints2;
return goodMatches;
}
public MatOfDMatch filterMatchesByHomography(MatOfDMatch matches) {
MatOfKeyPoint keypoints1 = keypointers1;
MatOfKeyPoint keypoints2 = keypointers2;
List<Point> lp1 = new ArrayList<Point>();
List<Point> lp2 = new ArrayList<Point>();
KeyPoint[] k1 = keypoints1.toArray();
KeyPoint[] k2 = keypoints2.toArray();
List<DMatch> matches_original = matches.toList();
if (matches_original.size() < 4) {
MatOfDMatch mat = new MatOfDMatch();
return mat;
}
// Add matches keypoints to new list to apply homography
for (DMatch match : matches_original) {
Point kk1 = k1[match.queryIdx].pt;
Point kk2 = k2[match.trainIdx].pt;
lp1.add(kk1);
lp2.add(kk2);
}
//srcPoints = new MatOfPoint2f(lp1.toArray(new Point[0]));
//dstPoints = new MatOfPoint2f(lp2.toArray(new Point[0]));
Mat mask = new Mat();
//Mat homography = Calib3d.findHomography(srcPoints, dstPoints, Calib3d.LMEDS, 0.2, mask);
List<DMatch> matches_homo = new ArrayList<DMatch>();
int size = (int) mask.size().height;
for (int i = 0; i < size; i++) {
if (mask.get(i, 0)[0] == 1) {
DMatch d = matches_original.get(i);
matches_homo.add(d);
}
}
MatOfDMatch mat = new MatOfDMatch();
mat.fromList(matches_homo);
//Highgui.imwrite("img-matchesWithRect.png", mat);
return mat;
}
public void drawMatches(Mat img1, Mat img2, MatOfDMatch matches, boolean imageOnly) {
Mat out = new Mat();
MatOfKeyPoint key2 = keypointers2;
MatOfKeyPoint key1 = keypointers1;
//Imgproc.cvtColor(img1, im1, Imgproc.COLOR_BGR2RGB);
//Imgproc.cvtColor(img2, im2, Imgproc.COLOR_BGR2RGB);
if (imageOnly) {
MatOfDMatch emptyMatch = new MatOfDMatch();
MatOfKeyPoint emptyKey1 = new MatOfKeyPoint();
MatOfKeyPoint emptyKey2 = new MatOfKeyPoint();
Features2d.drawMatches(img1, emptyKey1, img2, emptyKey2, emptyMatch, out);
} else {
Features2d.drawMatches(img1, key1, img2, key2, matches, out);
}
//Imgproc.cvtColor(out, out, Imgproc.COLOR_BGR2RGB);
Core.putText(out, "FRAME", new Point(img1.width() / 2, 30), Core.FONT_HERSHEY_PLAIN, 2, new Scalar(0, 255, 255), 3);
Core.putText(out, "MATCHED", new Point(img1.width() + img2.width() / 2, 30), Core.FONT_HERSHEY_PLAIN, 2, new Scalar(255, 0, 0), 3);
Highgui.imwrite("img-drawnMatches.png", out);
}
public void drawWithRect(Mat img1, Mat img2, MatOfPoint2f obj, MatOfPoint2f scene, Mat outputImg){
//run homography on object and scene points
Mat H = Calib3d.findHomography(obj, scene, Calib3d.RANSAC, 5);
Mat tmp_corners = new Mat(4, 1, CvType.CV_32FC2);
Mat scene_corners = new Mat(4, 1, CvType.CV_32FC2);
//get corners from object
tmp_corners.put(0, 0, new double[]{0, 0});
tmp_corners.put(1, 0, new double[]{img2.cols(), 0});
tmp_corners.put(2, 0, new double[]{img2.cols(), img2.rows()});
tmp_corners.put(3, 0, new double[]{0, img2.rows()});
Core.perspectiveTransform(tmp_corners, scene_corners, H);
Core.line(outputImg, new Point(scene_corners.get(0, 0)), new Point(scene_corners.get(1, 0)), new Scalar(0, 255, 0), 4);
Core.line(outputImg, new Point(scene_corners.get(1, 0)), new Point(scene_corners.get(2, 0)), new Scalar(0, 255, 0), 4);
Core.line(outputImg, new Point(scene_corners.get(2, 0)), new Point(scene_corners.get(3, 0)), new Scalar(0, 255, 0), 4);
Core.line(outputImg, new Point(scene_corners.get(3, 0)), new Point(scene_corners.get(0, 0)), new Scalar(0, 255, 0), 4);
Highgui.imwrite("img-matchesWithRect.png", outputImg);
}
公共列表子列表良好匹配(列出良好匹配){
集合。排序(良好匹配,(DMatch o1,DMatch o2)->{
如果(o1.距离氧2.距离){
返回1;
}
返回0;
});
如果(良好匹配.size()>10){
良好匹配=良好匹配。子列表(0,10);
}
返回良好的_匹配;
}
公共列表计算直方图(Mat图像){
Imgproc.cvtColor(图像,图像,Imgproc.COLOR_BGR2HSV);
列出hsv_平面=新建ArrayList();
核心分割(图像、hsv_平面);
MatOfInt histSize=新MatOfInt(256);
最终MatOfFloat历史范围=新MatOfFloat(0f,256f);
布尔累积=真;
Mat h_hist=新Mat();
Mat s_hist=新Mat();
Mat v_hist=新Mat();
//打破渠道
列表h_平面=新的ArrayList();
列表s_平面=新的ArrayList();
List v_plane=new ArrayList();
h_平面。添加(hsv_平面。获取(0));
添加(hsv_planes.get(1));
v_plane.add(hsv_planes.get(2));
Imgproc.calcHist(h_平面,新MatOfInt(0),新Mat(),h_历史,历史大小,历史范围,累积);
Imgproc.calcHist(s_平面,新MatOfInt(0),新Mat(),s_hist,histSize,histRange,累加);
Imgproc.calcHist(v_平面,新MatOfInt(0),新Mat(),v_hist,histSize,histRange,累加);
//绘制组合直方图
int hist_w=512;
int hist_h=600;
long bin_w=数学圆((双)历史w/256);
Mat histImage=新Mat(hist_h、hist_w、CvType.CV_8UC3、新标量(0,0,0));
normalize(h_hist,h_hist,3,histImage.rows(),Core.NORM_MINMAX,-1,new Mat());
Core.normalize(s_hist,s_hist,3,histImage.rows(),Core.NORM_MINMAX,-1,new Mat());
规范化(v_hist,v_hist,3,histImage.rows(),Core.NORM_MINMAX,-1,new Mat());
对于(int i=1;i<256;i++){
点p1=新点(bin_w*(i-1),hist_h-Math.round(h_hist.get(i-1,0)[0]);
点p2=新点(bin_w*(i),hist_h-Math.round(h_hist.get(i,0)[0]);
核心线(histImage,p1,p2,红色,2,8,0);
点p3=新点(bin_w*(i-1),hist_h-Math.round(s_hist.get(i-1,0)[0]);
点p4=新点(bin_w*(i),hist_h-数学圆(s_hist.get(i,0)[0]);
核心线(histImage,p3,p4,绿色,2,8,0);
点p5=新点(bin_w*(i-1),hist_h-Math.round(v_hist.get(i-1,0)[0]);
点p6=新点(bin_w*(i),hist_h-数学圆整(v_hist.get(i,0)[0]);
核心线(histImage,p5,p6,蓝色,2,8,0);
}
imwrite(“img histogram.jpg”,histImage);
System.out.println(“历史大小为:”+hsv_planes.size());
列表直方图=新的ArrayList();
直方图。添加(h_hist);
直方图。添加(s_hist);
直方图。添加(v_hist);
返回直方图;
}
公共Mat识别LOWSAT(Mat图像){
Mat hsvTargetImage=新Mat();
Imgproc.cvt颜色(图像,hsv目标图像,Imgproc.COLOR\u BGR2HSV);
列出hsv_平面=新建ArrayList();
堆芯分割(hsv目标图像、hsv_平面);
//获得饱和通道
Mat s_hist=hsv_平面。获取(1);
Imgproc.threshold(s_hist,s_hist,65255,Imgproc.THRESH_二进制);
imwrite(“img saturation.png”,s_hist);
返回s_hist;
}
公共Mat getBackProjOfHueTemplate(Mat图像、Mat色调直方图){
Mat hsvTargetImage=新Mat();
Imgproc.cvt颜色(图像,hsv目标图像,Imgproc.COLOR\u BGR2HSV);
列出hsv_平面=新建ArrayList();
堆芯分割(hsv目标图像、hsv_平面);
Mat backProj=新Mat();
最终MatOfFloat范围=新MatOfFloat(0f、256f);
Imgproc.calcBackProject(hsv_平面,新马托芬特(0),色调直方图,背景投影,范围,4);
imwrite(“img backProj.png”,backProj);
返回项目;
}
公共Mat meanShift(Mat图像){
Mat map=新Mat();
Rect Rect=新的Rect();
TermCriteria术语=新的TermCriteria();
term.maxCount=100;
term.type=TermCriteria.EPS;
项ε=0.1;
图像,地图,0.5,0.5,5,术语;
imwrite(“img meanshift.png”,map);
返回图;
}
公共匹配过滤器匹配(Mat img1、Mat img2){
FeatureDetector=FeatureDetector.create(FeatureDetector.SIFT);
DescriptorExtractor descriptor=DescriptorExtractor.create(DescriptorExtractor.BRISK);
DescriptorMatcher matcher=DescriptorMatcher.create(DescriptorMatcher.BRUTEFORCE_HAMMING);
//第一张照片
//Imgproc.cvt颜色(img1、img1、Imgproc.COLOR_rgb2灰色);
材料描述符1=新材料();
MatOfKeyPoint keypoints1=新的MatOfKeyPoint();
检测器。检测(img1,关键点1);
compute(img1,keypoints1,描述符1);
//第二张照片
//Imgproc.cvt颜色(img2、img2、Imgproc.COLOR_rgb2灰色);
材料描述符2=新材料();
MatOfKeyPoint keypoints2=新的MatOfKeyPoint();
检测器。检测(img2,关键点2);
描述符计算机
public static void main(String args[]) {
System.load(new File("/usr/local/Cellar/opencv/2.4.9/share/OpenCV/java/libopencv_java249.dylib").getAbsolutePath());
Mat img1 = Highgui.imread(scenesD);
Mat img2 = Highgui.imread(objectD);
MeanShift Tester = new MeanShift();
List<Mat> histogramsList;
Mat hue_histogram;
Mat saturationChannel;
Mat getBackProjOfHueTemp;
//Calulate Histogram of Object
histogramsList = Tester.calculateHistograms(img2);
//Get saturation channel of scene
saturationChannel = Tester.identifyLowSat(img1);
//Get hue of calculated object histogram
hue_histogram = histogramsList.get(0);
//Get back projection of object from calculated hue histogram template
getBackProjOfHueTemp = Tester.getBackProjOfHueTemplate(img2, hue_histogram);
//Filtering matches
MatOfDMatch matches = Tester.filterMatches(saturationChannel, getBackProjOfHueTemp);
MatOfDMatch homo_matches = Tester.filterMatchesByHomography(matches);
//Draw img unto screen;
Tester.drawMatches(saturationChannel, getBackProjOfHueTemp, homo_matches, false);
}
Rect sub_rect = new Rect(min_x, min_y, max_x - min_x, max_y - min_y);
Mat sub_region = image(sub_rect);