OpenCV detecting ROI, creating submat and copy to original mat - java

i'm trying to gray the faces of all people in an image. While I can detect their faces and gray them into smaller mat(s), I'm unable to 'copy' the grayed faces to the original mat. Such that the end result will have a mat with all faces in gray.
faceDetector.detectMultiScale(mat, faceDetections);
for (Rect rect : faceDetections.toArray())
{
Rect rectCrop = new Rect(rect.x, rect.y, rect.width, rect.height);
Mat imageROI = new Mat(mat,rectCrop);
//convert to B&W
Imgproc.cvtColor(imageROI, imageROI, Imgproc.COLOR_RGB2GRAY);
//Uncomment below will grayout the faces (one by one) but my objective is to have them grayed out on the original mat only.
//Highgui.imwrite(JTestUtil.DESKTOP_PATH+"cropImage_"+(++index)+".jpg",imageROI);
//add to mat? doesn't do anything :-(
mat.copyTo(imageROI);
}

imageROI is a 3 or 4 channel image. cvtColor to gray gives a single channel output and the imageROI's reference to mat is probably destroyed.
Use a buffer for gray conversion and convert back to RGBA or RGB with dst as imageROI.
faceDetector.detectMultiScale(mat, faceDetections);
for (Rect rect : faceDetections.toArray())
{
Rect rectCrop = new Rect(rect.x, rect.y, rect.width, rect.height);
//Get ROI
Mat imageROI = mat.submat(rectCrop);
//Move this declaration to onCameraViewStarted
Mat bw = new Mat();
//Use Imgproc.COLOR_RGB2GRAY for 3 channel image.
Imgproc.cvtColor(imageROI, bw, Imgproc.COLOR_RGBA2GRAY);
Imgproc.cvtColor(bw, imageROI, Imgproc.COLOR_GRAY2RGBA);
}
The result looks like

Related

OpenCV: how to change color of all non transparent pixels to black?

I use OpenCV (Java) and I want to change color of all the non transparent pixels in my Mat to black (colors defined in ARGB_8888 but could be another format)
How can I do that ?
Mat mat = new Mat();
bmp32 = bitmap.copy(Bitmap.Config.ARGB_8888, true);
Utils.bitmapToMat(bmp32, mat);
// and then ????
Thanks !
// allocate space as mixChannels requires so
Mat bgr = new Mat(mat.size(), CvType.CV_8UC3);
Mat alpha = new Mat(mat.size(), CvType.CV_8U);
List<Mat> src = new ArrayList<Mat>();
src.add(mat);
List<Mat> dst = new ArrayList<Mat>();
dst.add(alpha);
dst.add(bgr);
// A->alpha, RGB->bgr in reverse order
MatOfInt fromTo = new MatOfInt(0,0, 1,3, 2,2, 3,1);
mixChannels(src, dst, fromTo);
// now, make non-transparent parts black
Mat mask;
compare​(alpha, Scalar(0), mask, opencv_core.CMP_EQ);
Mat res;
Core.bitwise_and(bgr, bgr, res, mask);

Loading jpg image over mat frame opencv java

I have hand detection code right now that creates a green rectangle around the hand when detected. However, I want to fill the rectangle with another jpeg image. I was thinking of using ImagePattern where the image gets embedded inside the shape however that did not seem to work in my program.
Here is my code for creating the rectangle around the hand :
Imgproc.rectangle(frame, handsArray[i].tl(), handsArray[i].br(), new Scalar(0, 255, 0), 3);
The frame is a Mat and Imgproc is a opencv, javacv function.
Can someone please help me with this problem? I am struggling
Regards
Green Rectangle Around The Hand that needs to be filled
BufferedImage bi = null;
try {
bi = ImageIO.read(new File(trollFace));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Mat mat = new Mat(bi.getHeight(), bi.getWidth(), CvType.CV_8UC3);
byte[] data = ((DataBufferByte) bi.getRaster().getDataBuffer()).getData();
mat.put(0, 0, data);
You can do it in these steps:
Submat the rectangle from your source image
Mat submat = src.submat(new Rect(200, 200, 100, 100));
Now copy the sencond image into the submat
src2.copyTo(submat);
Note: Before copying, insure the size of the second image is the same as the rectangle, if not you can use the resize() function of the Imgprc class to resize the Mat. And it is that.
Update: The below is the example.
Mat src = Imgcodecs.imread("C:\\src1.jpg");
Mat src2 = Imgcodecs.imread("C:\\src2.jpg");
Imgproc.resize(src2, src2, new Size(100, 100));
Mat submat = src.submat(new Rect(200, 200, 100, 100));
src2.copyTo(submat);
// now you can do what you want with the src1

How to crop rectangles in opencv?

I manage to draw two rectangles from an image I captured. The question is, how to crop them out and save them individually so that I can perform my OCR in each of it? I have tried searching but I can't find what I wanted...
What I have done so far ..
Mat imageMat = new Mat();
Mat resizeImg = new Mat();
Mat hierarchy = new Mat();
//Size(width,height)
Size imageSize = new Size(1000,800);
Utils.bitmapToMat(image, imageMat);
//Resize Image
Imgproc.resize(imageMat,resizeImg,imageSize);
//convert the resized image to bitmap
image = Bitmap.createBitmap(resizeImg.cols(), resizeImg.rows(),
Bitmap.Config.ARGB_8888);
//convert back to Mat
Utils.bitmapToMat(image, imageMat);
//Create rectangles
Imgproc.rectangle(imageMat,new Point(0,150), new Point(500,250), new Scalar(255, 0, 255),1);
Imgproc.rectangle(imageMat,new Point(0,500), new Point(650,650), new Scalar(255, 0, 255),1);
//What I have tried doing
Rect rectCrop = new Rect(0,150,500,250);
Mat image_output= imageMat.submat(rectCrop);
Bitmap Cropimage = Bitmap.createBitmap(imageMat.cols(), imageMat.rows(), Bitmap.Config.ARGB_8888);
Utils.bitmapToMat(Cropimage, image_output);
//TODO: save only the content in the rectangles to MAT
//testing purpose
Utils.matToBitmap(imageMat,image);
imageView.setImageBitmap(image);
This is how to get croped image with rectangular shape.
Rect rect = new Rect(x1, y1, x2, y2);
Mat cropedMat = new Mat(mat, rect);
if you want you can convert croped mat to bitmap
Bitmap Cropedimage = Bitmap.createBitmap(cropedMat.cols(), cropedMat.rows(), Bitmap.Config.ARGB_8888);
Utils.matToBitmap(cropedMat, Cropedimage);

JavaCV detect captcha letters on a binary image

I'm new to JavaCv. My task is to find symbols on an image and generate pictures with single symbol on each other.
Firstly, I have this picture:
Then I do thresholding and get this:
I'm trying to use cvFindContours an then draw a rectangle around each symbol, my code:
String filename = "captcha.jpg";
IplImage firstImage=cvLoadImage(filename);
Mat src = imread(filename, CV_LOAD_IMAGE_GRAYSCALE);
Mat dst = new Mat();
threshold(src, dst, 200, 255, 0);
imwrite("out.jpg", dst);
IplImage iplImage=cvLoadImage("out.jpg",CV_8UC1);
CvMemStorage memStorage=CvMemStorage.create();
CvSeq contours=new CvSeq();
cvFindContours(iplImage,memStorage,contours,Loader.sizeof(CvContour.class),CV_RETR_CCOMP,CV_CHAIN_APPROX_SIMPLE,cvPoint(0,0));
CvSeq ptr;
CvRect bb;
for (ptr=contours;ptr!=null;ptr=ptr.h_next()){
bb=cvBoundingRect(ptr);
cvRectangle(firstImage , cvPoint( bb.x(), bb.y() ),
cvPoint( bb.x() + bb.width(), bb.y() + bb.height()),
CvScalar.BLACK, 2, 0, 0 );
}
cvSaveImage("result.jpg",firstImage);
}
I want to get output like this:, but really I get this:
Please, need your help.
You're using "out.jpg" image for findContour().
When you save dst Mat into "out.jpg", JPEG format automatically quantizes your original pixel data and creates noises to your image.
Save dst to "out.png" rather than "out.jpg", or use dst Mat directly into findContour().
Source Code ADDED: C++ version
string filename = "captcha.jpg";
Mat src = imread(filename);
Mat gray;
cvtColor(src, gray, CV_BGR2GRAY);
Mat thres;
threshold(gray, thres, 200, 255, 0);
vector<vector<Point>> contours;
vector<Vec4i> hierarchy;
findContours(thres.clone(), contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE);
Mat firstImage = src.clone();
for(int i=0; i< contours.sizes(); i++)
{
Rect r = boundingRect(contours[i]);
rectangle(firstImage, r, CV_RGB(255, 0, 0), 2);
}
imwrite("result.png", firstImage);

OpenCV on Android converting to grayscale not working

I am trying to convert some OpenCV Mat to grayscale for Contours detection algorithms. For some reason the image after convertion is all black. Mine code (b is Android Bitmap):
Mat tmp = new Mat (b.getWidth(), b.getHeight(), CvType.CV_8UC1);
Utils.bitmapToMat(b, tmp);
Imgproc.cvtColor(tmp, tmp, Imgproc.COLOR_BGR2GRAY);
//there could be some processing
Imgproc.cvtColor(tmp, tmp, Imgproc.COLOR_GRAY2BGRA, 4);
Utils.matToBitmap(tmp, b);
And now I am drawing this bitmap and it is all black. When I applied contour detection to this bitmap (in place of comment) there were no match, so I assume problem is with convertion. After removing convertion (simply call bitmapToMat and matToBitmap) then bitmap is not all black so convertion to Mat are also working. Bitmap is in ARGB_8888 and there are no errors, just the output bitmap is all black.
Edit: Just to be sure I tried to save a bitmap with ocv imwrite - it's still all black so the problem is for 100% at cvtColor...
If the bitmap b is from the android device, then try using COLOR_RGB2GRAY instead of COLOR_BGR2GRAY because BGR is the default pixel format for OpenCV images, not all images.
Try this code:
Mat tmp = new Mat (b.getWidth(), b.getHeight(), CvType.CV_8UC1);
Utils.bitmapToMat(b, tmp);
Imgproc.cvtColor(tmp, tmp, Imgproc.COLOR_RGB2GRAY);
//there could be some processing
Imgproc.cvtColor(tmp, tmp, Imgproc.COLOR_GRAY2RGB, 4);
Utils.matToBitmap(tmp, b);
I tried this method and it works perfectly, first you must convert it into grey scale, then to Canny, and finally to Bitmap.
this function returns a black and white image.
public static Bitmap edgesim(Mat img1) {
Bitmap image1;
//mat gray img1 holder
Mat imageGray1 = new Mat();
//mat canny image
Mat imageCny1 = new Mat();
//mat canny image
Mat imageCny2 = new Mat();
/////////////////////////////////////////////////////////////////
//Convert img1 into gray image
Imgproc.cvtColor(img1, imageGray1, Imgproc.COLOR_BGR2GRAY);
//Canny Edge Detection
Imgproc.Canny(imageGray1, imageCny1, 10, 100, 3, true);
///////////////////////////////////////////////////////////////////
//////////////////Transform Canny to Bitmap/////////////////////////////////////////
image1= Bitmap.createBitmap(imageCny1.cols(), imageCny1.rows(), Bitmap.Config.ARGB_8888);
Utils.matToBitmap(imageCny1, image1);
return image1;
}

Categories