OpenCV 检测最大矩形产生令人费解的结果
OpenCV detecting largest rectangle yields puzzling results
我的目标是检测图像中最大的矩形,无论它是否倾斜。经过一些研究和谷歌搜索后,我想出了一个理论上应该有效的代码,但是在一半的情况下,我看到了令人费解的结果。
我在 Android 中使用了 OpenCV,这是代码:
private void find_parallels() {
Utils.bitmapToMat(selectedPicture,img);
Mat temp = new Mat();
Imgproc.resize(img,temp,new Size(640,480));
img = temp.clone();
Mat imgGray = new Mat();
Imgproc.cvtColor(img,imgGray,Imgproc.COLOR_BGR2GRAY);
Imgproc.GaussianBlur(imgGray,imgGray,new Size(5,5),0);
Mat threshedImg = new Mat();
Imgproc.adaptiveThreshold(imgGray,threshedImg,255,Imgproc.ADAPTIVE_THRESH_GAUSSIAN_C,Imgproc.THRESH_BINARY,11,2);
List<MatOfPoint> contours = new ArrayList<>();
Mat hierarchy = new Mat();
Mat imageContours = imgGray.clone();
Imgproc.cvtColor(imageContours,imageContours,Imgproc.COLOR_GRAY2BGR);
Imgproc.findContours(threshedImg,contours,hierarchy,Imgproc.RETR_TREE,Imgproc.CHAIN_APPROX_SIMPLE);
max_area = 0;
int num = 0;
for (int i = 0; i < contours.size(); i++) {
area = Imgproc.contourArea(contours.get(i));
if (area > 100) {
MatOfPoint2f mop = new MatOfPoint2f(contours.get(i).toArray());
peri = Imgproc.arcLength(mop, true);
Imgproc.approxPolyDP(mop, approx, 0.02 * peri, true);
if(area > max_area && approx.toArray().length == 4) {
biggest = approx;
num = i;
max_area = area;
}
}
}
selectedPicture = Bitmap.createBitmap(640,480, Bitmap.Config.ARGB_8888) ;
Imgproc.drawContours(img,contours,num,new Scalar(0,0,255));
Utils.matToBitmap(img, selectedPicture);
imageView1.setImageBitmap(selectedPicture);}
在某些情况下,它的效果非常好,如图所示(请参见显示器边框和屏幕之间的白线。抱歉颜色不对):
有效示例:
然而,在这张图片中,以及屏幕呈灰色的大多数图片中,它会产生疯狂的结果。
无效示例:
尝试使用形态学,用相同的内核先扩张再腐蚀应该会更好。
或者使用 pyrDown + pyrUp,或者只是模糊它。
总之使用低通滤波器class的方法,因为你感兴趣的对象比噪声大得多。
我的目标是检测图像中最大的矩形,无论它是否倾斜。经过一些研究和谷歌搜索后,我想出了一个理论上应该有效的代码,但是在一半的情况下,我看到了令人费解的结果。
我在 Android 中使用了 OpenCV,这是代码:
private void find_parallels() {
Utils.bitmapToMat(selectedPicture,img);
Mat temp = new Mat();
Imgproc.resize(img,temp,new Size(640,480));
img = temp.clone();
Mat imgGray = new Mat();
Imgproc.cvtColor(img,imgGray,Imgproc.COLOR_BGR2GRAY);
Imgproc.GaussianBlur(imgGray,imgGray,new Size(5,5),0);
Mat threshedImg = new Mat();
Imgproc.adaptiveThreshold(imgGray,threshedImg,255,Imgproc.ADAPTIVE_THRESH_GAUSSIAN_C,Imgproc.THRESH_BINARY,11,2);
List<MatOfPoint> contours = new ArrayList<>();
Mat hierarchy = new Mat();
Mat imageContours = imgGray.clone();
Imgproc.cvtColor(imageContours,imageContours,Imgproc.COLOR_GRAY2BGR);
Imgproc.findContours(threshedImg,contours,hierarchy,Imgproc.RETR_TREE,Imgproc.CHAIN_APPROX_SIMPLE);
max_area = 0;
int num = 0;
for (int i = 0; i < contours.size(); i++) {
area = Imgproc.contourArea(contours.get(i));
if (area > 100) {
MatOfPoint2f mop = new MatOfPoint2f(contours.get(i).toArray());
peri = Imgproc.arcLength(mop, true);
Imgproc.approxPolyDP(mop, approx, 0.02 * peri, true);
if(area > max_area && approx.toArray().length == 4) {
biggest = approx;
num = i;
max_area = area;
}
}
}
selectedPicture = Bitmap.createBitmap(640,480, Bitmap.Config.ARGB_8888) ;
Imgproc.drawContours(img,contours,num,new Scalar(0,0,255));
Utils.matToBitmap(img, selectedPicture);
imageView1.setImageBitmap(selectedPicture);}
在某些情况下,它的效果非常好,如图所示(请参见显示器边框和屏幕之间的白线。抱歉颜色不对):
有效示例:
然而,在这张图片中,以及屏幕呈灰色的大多数图片中,它会产生疯狂的结果。
无效示例:
尝试使用形态学,用相同的内核先扩张再腐蚀应该会更好。 或者使用 pyrDown + pyrUp,或者只是模糊它。
总之使用低通滤波器class的方法,因为你感兴趣的对象比噪声大得多。