1 | initial version |
So, this is my implementation of your methods, in Java:
private List<Rect> divideHW(Mat src,boolean dim, double threshold1, double threshold2)
{
List<Rect> rois=new ArrayList<>();
Mat gray, reduced, canny;
gray=new Mat();
if( src.channels() == 1 )
{
gray = src;
}
if( src.channels() == 3 )
{
gray=new Mat();
cvtColor( src, gray, Imgproc.COLOR_BGR2GRAY );
}
reduced=new Mat();
int value=0;
if(dim)value=1;
reduce(gray, reduced, value, REDUCE_AVG);
canny=new Mat();
Canny(reduced, canny, threshold1, threshold2, 3, true);
MatOfPoint pts =new MatOfPoint();
findNonZero(canny,pts);
List<Point> pts_ref=pts.toList();
Rect rect=new Rect(0,0,gray.cols(),gray.rows());
int ref_x = 0;
int ref_y = 0;
for( int i=0; i< pts_ref.size(); i++ )
{
if( dim )
{
rect.height = (int)(pts_ref.get(i).y-ref_y);
rois.add(rect);
rect.y = (int)pts_ref.get(i).y;
ref_y = rect.y;
if( i == pts_ref.size()-1 )
{
rect.height = gray.rows() -(int) pts_ref.get(i).y;
rois.add( rect );
}
}
else
{
rect.width =(int)pts_ref.get(i).x-ref_x;
rois.add( rect );
rect.x = (int)pts_ref.get(i).x;
ref_x = rect.x;
if( i == pts_ref.size()-1 )
{
rect.width = gray.cols() - (int)pts_ref.get(i).x;
rois.add( rect );
}
}
}
return rois;
}
private void algorithm()
{
Bitmap memoryPhoto;
Mat original = new Mat();
Mat gray=new Mat();
String photo_path =Environment.getExternalStorageDirectory().toString()+
+"/shelf_analyzer_results/shelf.jpg";
memoryPhoto=BitmapFactory.decodeFile(photo_path);
Utils.bitmapToMat(memoryPhoto, original);
Mat clone=original.clone();
List<Rect> rois;
rois= divideHW( clone, true, 0, 255 );
int counter=0;
for(int i=0;i<rois.size();i++)
{
Mat roi_h=new Mat(original,rois.get(i));
List<Rect> rois_w=divideHW(roi_h,false,0,255);
for( int j=0; j< rois_w.size(); j++ )
{
rois_w.get(j).y += rois.get(i).y;
//here I want to save the single "product" found on the shelf, so i don't have
//to draw it, like in you example
Mat product=new Mat(original,rois_w.get(j));
saveImage(stdDir,product,"product-"+counter+".jpeg");
counter++;
}
}
}
2 | No.2 Revision |
So, this is my implementation of your methods, in Java:
private List<Rect> divideHW(Mat src,boolean dim, double threshold1, double threshold2)
{
List<Rect> rois=new ArrayList<>();
Mat gray, reduced, canny;
gray=new Mat();
if( src.channels() == 1 )
{
gray = src;
}
if( src.channels() == 3 )
{
gray=new Mat();
cvtColor( src, gray, Imgproc.COLOR_BGR2GRAY );
}
reduced=new Mat();
int value=0;
if(dim)value=1;
reduce(gray, reduced, value, REDUCE_AVG);
canny=new Mat();
Canny(reduced, canny, threshold1, threshold2, 3, true);
MatOfPoint pts =new MatOfPoint();
findNonZero(canny,pts);
List<Point> pts_ref=pts.toList();
Rect rect=new Rect(0,0,gray.cols(),gray.rows());
int ref_x = 0;
int ref_y = 0;
for( int i=0; i< pts_ref.size(); i++ )
{
if( dim )
{
rect.height = (int)(pts_ref.get(i).y-ref_y);
rois.add(rect);
rect.y = (int)pts_ref.get(i).y;
ref_y = rect.y;
if( i == pts_ref.size()-1 )
{
rect.height = gray.rows() -(int) pts_ref.get(i).y;
rois.add( rect );
}
}
else
{
rect.width =(int)pts_ref.get(i).x-ref_x;
rois.add( rect );
rect.x = (int)pts_ref.get(i).x;
ref_x = rect.x;
if( i == pts_ref.size()-1 )
{
rect.width = gray.cols() - (int)pts_ref.get(i).x;
rois.add( rect );
}
}
}
return rois;
}
private void algorithm()
{
Bitmap memoryPhoto;
Mat original = new Mat();
Mat gray=new Mat();
String photo_path =Environment.getExternalStorageDirectory().toString()+
+"/shelf_analyzer_results/shelf.jpg";
memoryPhoto=BitmapFactory.decodeFile(photo_path);
Utils.bitmapToMat(memoryPhoto, original);
Mat clone=original.clone();
List<Rect> rois;
rois= divideHW( clone, true, 0, 255 );
int counter=0;
for(int i=0;i<rois.size();i++)
{
Mat roi_h=new Mat(original,rois.get(i));
List<Rect> rois_w=divideHW(roi_h,false,0,255);
for( int j=0; j< rois_w.size(); j++ )
{
rois_w.get(j).y += rois.get(i).y;
//here I want to save the single "product" found on the shelf, so i don't have
//to draw it, like in you example
Mat product=new Mat(original,rois_w.get(j));
saveImage(stdDir,product,"product-"+counter+".jpeg");
counter++;
}
}
}
This implementation works in terms of execution without compile-time errors but, it gives me zero product found at each time!
3 | No.3 Revision |
So, UPDATE 1
Today I debugged a little and found out some problems that, probably, in c++ don't shows up.
inside this is my implementation part of your methods, in Java:divideHW method:
private List<Rect> divideHW(Mat src,boolean dim, double threshold1, double threshold2)
{
List<Rect> rois=new ArrayList<>();
Mat gray, reduced, canny;
gray=new Mat();
if( src.channels() == 1 )
{
gray = src;
}
if( src.channels() == 3 )
{
gray=new Mat();
cvtColor( src, gray, Imgproc.COLOR_BGR2GRAY );
}
reduced=new Mat();
int value=0;
if(dim)value=1;
reduce(gray, reduced, value, REDUCE_AVG);
canny=new Mat();
Canny(reduced, canny, threshold1, threshold2, 3, true);
MatOfPoint pts =new MatOfPoint();
findNonZero(canny,pts);
List<Point> pts_ref=pts.toList();
Rect rect=new Rect(0,0,gray.cols(),gray.rows());
int ref_x = 0;
int ref_y = 0;
for( int i=0; i< pts_ref.size(); i++ )
{
if( dim )
{
if(i!=pts_ref.size()-1 ){
rect.height = (int)(pts_ref.get(i).y-ref_y);
rois.add(rect);
if(rect.height>100)
{
Rect r=rect.clone();
rois.add(r);
}
rect.y = (int)pts_ref.get(i).y;
ref_y = rect.y;
if( i == pts_ref.size()-1 )
}
else
{
rect.height = gray.rows() -(int) pts_ref.get(i).y;
rois.add( rect );
if(rect.height>100)
{
Rect r=rect.clone();
rois.add(r);
}
}
}
else
{
if( i != pts_ref.size()-1 )
{
rect.width =(int)pts_ref.get(i).x-ref_x;
rois.add( rect );
= (int) pts_ref.get(i).x - ref_x;
if(rect.width>50){
Rect r=rect.clone();
rois.add(r);
}
rect.x = (int)pts_ref.get(i).x;
(int) pts_ref.get(i).x;
ref_x = rect.x;
if( i == pts_ref.size()-1 )
}
else
{
rect.width = gray.cols() - (int)pts_ref.get(i).x;
rois.add( rect );
}
}
}
return rois;
}
private void algorithm()
{
Bitmap memoryPhoto;
Mat original = new Mat();
Mat gray=new Mat();
String photo_path =Environment.getExternalStorageDirectory().toString()+
+"/shelf_analyzer_results/shelf.jpg";
memoryPhoto=BitmapFactory.decodeFile(photo_path);
Utils.bitmapToMat(memoryPhoto, original);
Mat clone=original.clone();
List<Rect> rois;
rois= divideHW( clone, true, 0, 255 );
int counter=0;
for(int i=0;i<rois.size();i++)
{
Mat roi_h=new Mat(original,rois.get(i));
List<Rect> rois_w=divideHW(roi_h,false,0,255);
for( int j=0; j< rois_w.size(); j++ )
{
rois_w.get(j).y += rois.get(i).y;
//here I want to save the single "product" found on the shelf, so i don't have
//to draw it, like in you example
Mat product=new Mat(original,rois_w.get(j));
saveImage(stdDir,product,"product-"+counter+".jpeg");
counter++;
}
}
if(rect.width>50){
Rect r=rect.clone();
rois.add(r);
}
}
}
}
This implementation I've added a clone() call to our just calculated rect, to avoid that pushing the rect without cloning, once the for loop finishes, all the N entries of rois are equal to the last rect analyzed..
Second, I've managed to control the minimum width and heights of rects, to avoid getting solutions not consistent (i.e. part of the background or part of unwanted boxes.
Now I succesfully can get my boxes, but not exactly. I can get a correct box, or multiple boxes together, or part of boxes (like half a box or a quarter of a box).
I will try now with another test image, then I will test if this approach works even with captured images from camera (taking photo in terms "perfect" front of execution without compile-time errors but, it gives me zero product found at each time!a shelf, to avoid perspective as mush as we can).
test 2 image