why dilate functin give different result when the parameteer is the same - java

I try to dilate three image of characters in java opencv. i found out than ever it same character with same font and size, after dilate the result is different. so i try with same image the result is still different. Here is my test code.
for (int j = 0; j < 3; j++) {
Mat InputSrc = openFile("src\\myOpencv\\ocr\\crop1.png");
Mat tempImg =new Mat();
Imgproc.cvtColor(InputSrc, tempImg, Imgproc.COLOR_BGR2GRAY);
Imgproc.threshold(tempImg, tempImg, 0, 255, Imgproc.THRESH_OTSU);
imageViewer.show(tempImg, "src");
Mat kernal5 = new Mat(5, 5, CV_8U);
Point midPoint = new Point(-1, -1);
Scalar scalarOne = new Scalar(1);
Mat binImg2 = new Mat();
Imgproc.dilate(tempImg, binImg2, kernal5, midPoint, 1, 1, scalarOne);
imageViewer.show(binImg2, "dilate");
}
thank

Related

OpenCV Java - Changing pixel color

I am trying to determine a way to change the pixel color of my masks from black to a different color. Unfortunately, I have not be able to determine a way to do this task. Essentially, what I am trying to do is take this image:
and convert the black portions to a color with values (255, 160, 130). I have tried several methods to try and achieve my goal. These include draw contours, setTo, and looping through the matrix. Unfortunately all of these attempts have failed. I have included the code and the resulting outcomes below.
Draw Contours method
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
Mat img = Imgcodecs.imread(
"C:\\Users\\Hassan\\Documents\\School\\Me\\COMP5900 Y\\Project\\Project\\src\\resources\\face.jpg");
Mat img_grey = new Mat();
Mat grad = new Mat(), grad_x = new Mat(), grad_y = new Mat();
Mat abs_grad_x = new Mat(), abs_grad_y = new Mat();
int ddepth = CvType.CV_32F;
int scale = 1;
int delta = 0;
Imgproc.GaussianBlur(img, img, new Size(3, 3), 0, 0, Core.BORDER_CONSTANT);
Imgproc.cvtColor(img, img_grey, Imgproc.COLOR_BGR2GRAY);
// Apply Sobel
Imgproc.Sobel(img_grey, grad_x, ddepth, 1, 0, 3, scale, delta, Core.BORDER_DEFAULT);
Imgproc.Sobel(img_grey, grad_y, ddepth, 0, 1, 3, scale, delta, Core.BORDER_DEFAULT);
// converting back to CV_8U
Core.convertScaleAbs(grad_x, abs_grad_x);
Core.convertScaleAbs(grad_y, abs_grad_y);
// Total Gradient (approximate)
Core.addWeighted(abs_grad_x, 0.5, abs_grad_y, 0.5, 0, grad);
Photo.fastNlMeansDenoising(grad, grad);
Imgproc.GaussianBlur(grad, grad, new Size(3, 3), 0, 0, Core.BORDER_CONSTANT);
// isolate background
Mat background = new Mat();
Imgproc.threshold(grad, background, 2, 255, Imgproc.THRESH_BINARY);
// draw contours
List<MatOfPoint> contours = new ArrayList<>();
Mat hierarchy = new Mat();
Imgproc.findContours(background, contours, hierarchy, Imgproc.RETR_TREE, Imgproc.CHAIN_APPROX_NONE);
Mat drawing = Mat.zeros(background.size(), CvType.CV_8UC3);
List<MatOfPoint> hullList = new ArrayList<>();
for (MatOfPoint contour : contours) {
MatOfInt hull = new MatOfInt();
Imgproc.convexHull(contour, hull);
Point[] contourArray = contour.toArray();
Point[] hullPoints = new Point[hull.rows()];
List<Integer> hullContourIdxList = hull.toList();
for (int i = 0; i < hullContourIdxList.size(); i++) {
hullPoints[i] = contourArray[hullContourIdxList.get(i)];
}
hullList.add(new MatOfPoint(hullPoints));
}
for (int i = 0; i < contours.size(); i++) {
Scalar color = new Scalar(255, 160, 130);
Imgproc.drawContours(drawing, contours, i, color);
//Imgproc.drawContours(drawing, hullList, i, color );
}
Note here, that I also tried using Imgproc.RETR_EXTERNAL as well, but that produced a completely black image. Also the name of the HighGui window is called "flood fill", but I just forgot to update the name.
setTo
// replace find and draw contours portion of code above
Mat out = new Mat();
background.copyTo(out);
out.setTo(new Scalar(255, 160, 130), background);
Iterating through matrix
// replace draw contours portion of code above
for (a = 0; a < background.rows(); a++) {
for(b = 0; b < background.cols(); b++) {
if(background.get(a,b)[0] == 0) {
//background.put(a, b, CvType.CV_16F, new Scalar(255, 160, 130));
double[] data = {255, 160, 130};
background.put(a, b, data);
}
}
}
The loop is promising, but I know it will not be efficient as I have 2 other masks that I would like to update as well. Could you please suggest an efficient method, that allows me to set the value for all three channels?
Thanks
I am not sure why you are doing many operations on the image but to me it looks like applying the mask and replacing the color efficiently. So if there are other complexities than please let me know.
Below is the code I was looking for in Java.
public static void main(String s[]) {
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
Mat matr =Imgcodecs.imread("/home/shariq/Desktop/test.png");
Mat result = new Mat();
//create a mask based on range
Core.inRange(matr, new Scalar(0), new Scalar(50), result);
Imgcodecs.imwrite("/home/shariq/Desktop/test_in.png", result);
//apply the mask with color you are looking for, note here scalar is in hsv
matr.setTo(new Scalar(130,160,255),result);
Imgcodecs.imwrite("/home/shariq/Desktop/result.png", matr);
}
We are creating a mask for the pixel values between 0-50 for black color using inRange method.
Core.inRange(matr, new Scalar(0), new Scalar(50), result);
This mask in result variable is than applied to original matrix using setTo method. The replacement color value is provided in HSV format through Scalar object. new Scalar(a,b,c) in HSV can be understand in RGB like this Red = c, Green = b and Blue = a.
matr.setTo(new Scalar(130,160,255),result);
Its quite fast compared to iterating the pixels one by one.

Detection of red circle-alike | openCV | Java

I am writing a program which need to detect red circle-alikes from this picture.
I have tried canny edge detection and find contours but none of them find this red "circles". I also tried to convert this to hsv and detect this by color but I couldn't determine good range for this color, maybe background color confuses it?
I put here a piece of my code with my final attempt..
Mat image = new Mat();
image = Imgcodecs.imread("image.jpg");
Mat hsvImage = new Mat();
Mat grayscaleImage = new Mat();
Mat binaryImage = new Mat();
Imgproc.blur(image, image, new Size(1, 1));
Imgproc.cvtColor(image, hsvImage, Imgproc.COLOR_BGR2HSV);
Imgproc.cvtColor(image, grayscaleImage, Imgproc.COLOR_BGR2GRAY);
Imgproc.equalizeHist(grayscaleImage, grayscaleImage);
Imgproc.Canny(grayscaleImage, grayscaleImage, 50, 150, 3,false);
List<MatOfPoint> contours = new ArrayList<MatOfPoint>();
Imgproc.findContours(grayscaleImage.clone(), contours, new Mat(), Imgproc.RETR_LIST, Imgproc.CHAIN_APPROX_SIMPLE);
for (int id=0;id<contours.size();id++){
MatOfPoint2f mop2f = new MatOfPoint2f();
contours.get(id).convertTo(mop2f,CvType.CV_32F);
RotatedRect rectangle = Imgproc.minAreaRect(mop2f);
if (rectangle.boundingRect().width>80)
Imgproc.drawContours(image,contours,id,new Scalar(0,255,0));
}
If you want to process that marked image, you really might want to detect colors. Typically this is done in HSV color-space.
Here is some C++ code to detect "red" color. The result isn't good enough to use findContours yet, but maybe after some dilation. Maybe you can convert the code to Java.
If you want to detect different color, change the line redMask = thresholdHue(hsv, 0, 20, 50, 50); to mask = thresholdHue(hsv, yourWantedHueColorValue, 20, 50, 50);`
// for example to shift a circluar hue-channel
cv::Mat shiftChannel(cv::Mat H, int shift, int maxVal = 180)
{
// CV_8UC1 only!
cv::Mat shiftedH = H.clone();
//int shift = 25; // in openCV hue values go from 0 to 180 (so have to be doubled to get to 0 .. 360) because of byte range from 0 to 255
for (int j = 0; j < shiftedH.rows; ++j)
for (int i = 0; i < shiftedH.cols; ++i)
{
shiftedH.at<unsigned char>(j, i) = (shiftedH.at<unsigned char>(j, i) + shift) % maxVal;
}
return shiftedH;
}
cv::Mat thresholdHue(cv::Mat hsvImage, int hueVal, int range = 30, int minSat = 50, int minValue = 50)
{
// hsvImage must be CV_8UC3 HSV image.
// hue val and range are in openCV's hue range (0 .. 180)
// range shouldnt be bigger than 90, because that's max (all colors), after shifting the hue channel.
// this function will
// 1. shift the hue channel, so that even colors near the border (red color!) will be detectable with same code.
// 2. threshold the hue channel around the value 90 +/- range
cv::Mat mask; // return-value
std::vector<cv::Mat> channels;
cv::split(hsvImage, channels);
int targetHueVal = 180 / 2; // we'll shift the hue-space so that the target val will always be 90 afterwards, no matter which hue value was chosen. This can be important if
int shift = targetHueVal - hueVal;
if (shift < 0) shift += 180;
cv::Mat shiftedHue = shiftChannel(channels[0], shift, 180);
// merge the channels back to hsv image
std::vector<cv::Mat> newChannels;
newChannels.push_back(shiftedHue);
newChannels.push_back(channels[1]);
newChannels.push_back(channels[2]);
cv::Mat shiftedHSV;
cv::merge(newChannels, shiftedHSV);
// threshold
cv::inRange(shiftedHSV, cv::Vec3b(targetHueVal - range, minSat, minValue), cv::Vec3b(targetHueVal + range, 255, 255), mask);
return mask;
}
int main(int argc, char* argv[])
{
cv::Mat input = cv::imread("C:/StackOverflow/Input/redCircleLikeContours.jpg");
cv::Mat redMask;
cv::Mat hsv;
cv::cvtColor(input, hsv, CV_BGR2HSV);
redMask = thresholdHue(hsv, 0, 20, 50, 50);
cv::imshow("red", redMask);
cv::imshow("input", input);
cv::imwrite("C:/StackOverflow/Output/redCircleLikeContoursMask.png", redMask);
cv::waitKey(0);
return 0;
}
Here's the result:
Here is my code if somebody would want to look :)
public static void main (String args[]){
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
Mat image = new Mat();
image = Imgcodecs.imread("imageorg.jpg");
if ( image == null) System.out.println("Image is fine");
else System.out.println("Wrong path to image");
Mat hsvImage = new Mat();
Imgproc.blur(image, image, new Size(3,3));
Imgproc.cvtColor(image, hsvImage, Imgproc.COLOR_BGR2HSV);
Mat redMask = new Mat();
redMask = thresholdHue(hsvImage,0,20,50,50);
Mat kernel = new Mat();
kernel = Imgproc.getStructuringElement(Imgproc.MORPH_DILATE, new Size(2,2));
Mat dilateMat = new Mat();
Imgproc.dilate(redMask, dilateMat, kernel);
Imgcodecs.imwrite("redCircleLikeContours.png", redMask);
List<MatOfPoint> contours = new ArrayList<MatOfPoint>();
Imgproc.findContours(dilateMat.clone(), contours, new Mat(), Imgproc.RETR_LIST, Imgproc.CHAIN_APPROX_SIMPLE);
List<MatOfPoint> removedContoursList = new ArrayList<MatOfPoint>();
for (int id=0;id<contours.size();id++){
MatOfPoint2f mop2f = new MatOfPoint2f();
contours.get(id).convertTo(mop2f,CvType.CV_32F);
RotatedRect rectangle = Imgproc.minAreaRect(mop2f);
if (rectangle.boundingRect().height<10){
removedContoursList.add(contours.get(id));
System.out.println("removing: "+rectangle.boundingRect());
contours.remove(id);
id--;
}
}
}
public static Mat thresholdHue(Mat hsvImage, int hueVal, int range, int minSat, int minValue)
{
Mat mask = new Mat();
List<Mat> channels = new ArrayList<Mat>();
Core.split(hsvImage, channels);
int targetHueVal = 180 / 2;
int shift = targetHueVal - hueVal;
if (shift < 0) shift += 180;
Mat shiftedHue = shiftChannel(channels.get(0), shift, 180);
List<Mat> newChannels = new ArrayList<Mat>();
newChannels.add(shiftedHue);
newChannels.add(channels.get(1));
newChannels.add(channels.get(2));
Mat shiftedHSV = new Mat();
Core.merge(newChannels, shiftedHSV);
Core.inRange(shiftedHSV, new Scalar(targetHueVal - range, minSat, minValue), new Scalar(targetHueVal + range, 255, 255), mask);
return mask;
}
private static Mat shiftChannel(Mat H, int shift, int maxVal)
{
Mat shiftedH = H.clone();
for (int j = 0; j < shiftedH.rows(); ++j)
for (int i = 0; i < shiftedH.cols(); ++i)
{
shiftedH.put(j, i,(shiftedH.get(j,i)[0] + shift) % maxVal);
}
return shiftedH;
}

Store histogram value in array to compare with input image - android opencv

I'm doing a project using opencv in android studio.
My project is about comparing colour histogram of an input image captured by camera with the 6 images that is stored in the drawable. The opencv function that I used is comparHist(). The purpose of the comparison is to know if the input image has matched colour to any images in the drawable.
My problem is I need to calculate colour histogram using calcHist() for every 6 images every time there is an input image(captured by camera) so that I can compare them. I was thinking to store the colour histogram value of 6 images in an array. Can I do so?
I was searching for a solution but there is none. Here is my code that I have done.
public int resultRecog() {
drawImg = BitmapFactory.decodeResource(getResources(), R.drawable.onefront);
Mat hsv_base = new Mat();
Mat hsv_test = new Mat();
Utils.bitmapToMat(drawImg, hsv_base);
Utils.bitmapToMat(pic, hsv_test);
/// Convert to HSV
Imgproc.cvtColor(hsv_base, hsv_base, Imgproc.COLOR_BGR2HSV);
Imgproc.cvtColor(hsv_test, hsv_test, Imgproc.COLOR_BGR2HSV);
/// h s bins value
MatOfInt histSize = new MatOfInt(40, 40);
//// ranges h=0-180, s=0-256
MatOfFloat ranges = new MatOfFloat(0f, 180f, 0f, 256f);
/// two channel
MatOfInt channels = new MatOfInt(0, 1);
Mat hist_base = new Mat();
Mat hist_test = new Mat();
ArrayList<Mat> histImages = new ArrayList<Mat>();
histImages.add(hsv_base);
Imgproc.calcHist(histImages, channels, new Mat(), hist_base, histSize, ranges, false);
Core.normalize(hist_base, hist_base, 0, 1, Core.NORM_MINMAX, -1, new Mat());
histImages = new ArrayList<Mat>();
histImages.add(hsv_test);
Imgproc.calcHist(histImages, channels, new Mat(), hist_test, histSize, ranges, false);
Core.normalize(hist_test, hist_test, 0, 1, Core.NORM_MINMAX, -1, new Mat());
double result = Imgproc.compareHist(hist_base, hist_test, 0);
drawImg.recycle();
drawImg = null;
int r;
if (result >= 0.15) {
r = 1;
} else {
drawImg = BitmapFactory.decodeResource(getResources(), R.drawable.fivefront);
Mat hsv_base5 = new Mat();
Utils.bitmapToMat(drawImg, hsv_base5);
Imgproc.cvtColor(hsv_base5, hsv_base5, Imgproc.COLOR_BGR2HSV);
Mat hist_base5 = new Mat();
ArrayList<Mat> histImages5 = new ArrayList<Mat>();
histImages5.add(hsv_base5);
Imgproc.calcHist(histImages5, channels, new Mat(), hist_base5, histSize, ranges, false);
Core.normalize(hist_base5, hist_base5, 0, 1, Core.NORM_MINMAX, -1, new Mat());
result = Imgproc.compareHist(hist_base5, hist_test, 0);
drawImg.recycle();
drawImg = null;
if (result >= 0.1) {
r = 5;
} else {
drawImg = BitmapFactory.decodeResource(getResources(), R.drawable.f10);
Mat hsv_base10 = new Mat();
Utils.bitmapToMat(drawImg, hsv_base10);
Imgproc.cvtColor(hsv_base10, hsv_base10, Imgproc.COLOR_BGR2HSV);
Mat hist_base10 = new Mat();
ArrayList<Mat> histImages10 = new ArrayList<Mat>();
histImages10.add(hsv_base10);
Imgproc.calcHist(histImages10, channels, new Mat(), hist_base10, histSize, ranges, false);
Core.normalize(hist_base10, hist_base10, 0, 1, Core.NORM_MINMAX, -1, new Mat());
result = Imgproc.compareHist(hist_base10, hist_test, 0);
drawImg.recycle();
drawImg = null;
if (result >= 0.1) {
r = 10;
} else {
drawImg = BitmapFactory.decodeResource(getResources(), R.drawable.fiftyfront);
Mat hsv_base50 = new Mat();
Utils.bitmapToMat(drawImg, hsv_base50);
Imgproc.cvtColor(hsv_base50, hsv_base50, Imgproc.COLOR_BGR2HSV);
Mat hist_base50 = new Mat();
ArrayList<Mat> histImages50 = new ArrayList<Mat>();
histImages50.add(hsv_base50);
Imgproc.calcHist(histImages50, channels, new Mat(), hist_base50, histSize, ranges, false);
Core.normalize(hist_base50, hist_base50, 0, 1, Core.NORM_MINMAX, -1, new Mat());
result = Imgproc.compareHist(hist_base50, hist_test, 0);
drawImg.recycle();
drawImg = null;
if (result >= 0.1) {
r = 50;
} else {
r = 0;
}
}//rm10
}//rm5
}//rm1
return r;
}
So my question is, can I store the colour histogram value (of 6 images stored in the drawable) in an array so that the application doesn't need to re-calculate the colour histogram every time there is input image captured by camera

OpenCV Java text segmentation

I am working on a licence plate recognition software using OpenCV, Tesseract and Java but experiencing issues, I cant seem to segment my text correctly, its not always that I get all characters to be detected and bounded with a bounding box these are some of my outputs with my code...and also when I detect the characters I never know which character is in which box so when I pass them through tesseract they get jumbled, how do I format my string?
This one fails despite the clearly visible characters:
Here Z and 6 fail to be detected even when 6 is clearly visible:
Below is my code:
originalFrame = image.clone();
roiColor = image.clone();
Imgproc.cvtColor(image, image, Imgproc.COLOR_BGR2GRAY, 0);
originalFrameGrayScale = image.clone();
Mat morph = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(9, 9));
Imgproc.morphologyEx(image, image, Imgproc.MORPH_TOPHAT, morph);
Imgproc.Sobel(image, image, -1, 2, 0);
Imgproc.GaussianBlur(image, image, new Size(5,5), 3,3);
Imgproc.morphologyEx(image, image, Imgproc.MORPH_CLOSE, morph);
Imgproc.threshold(image, image, 200, 255, Imgproc.THRESH_OTSU);
Vector<Rect> rectangles = detectionContour(image);
Mat roi = originalFrameGrayScale.clone();
if(!rectangles.isEmpty()){
roi = originalFrameGrayScale.submat(rectangles.get(0));
roiBlack = roi.clone();
roiColor = roiColor.submat(rectangles.get(0));
Imgproc.rectangle(originalFrame, rectangles.get(0).br(), rectangles.get(0).tl(), new Scalar(0,0,255), 2);
}
Imgproc.medianBlur(roi, roi, 3);
Imgproc.adaptiveThreshold(roi, roi, 225, Imgproc.ADAPTIVE_THRESH_GAUSSIAN_C, Imgproc.THRESH_BINARY, 15, 3);
roiBinarize = roi.clone();
Mat erode = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(1, 1));
Mat dilate = Imgproc.getStructuringElement(Imgproc.MORPH_RECT,new Size(1, 1));
Imgproc.morphologyEx(roi, roi, Imgproc.MORPH_OPEN, dilate);
Imgproc.morphologyEx(roi, roi, Imgproc.MORPH_OPEN, erode);
Imgproc.Canny(roi, roi, 150, 150 * 3, 3, true);
Vector<Rect> letters = detectionPlateCharacterContour(roi);
doTesseractOCR(letters, roiBinarize);
private static void doTesseractOCR(Vector<Rect> letters, Mat plate){
Tesseract instance = new Tesseract(); //
instance.setLanguage(LANGUAGE);
String resultPlate = "";
for(int i= 0; i < letters.size(); i++){
BufferedImage letter = OpenCvUtils.Mat2bufferedImage(plate.submat(letters.get(i)));
try {
String result = instance.doOCR(letter);
resultPlate += result + " position "+i;
} catch (TesseractException e) {
System.err.println(e.getMessage());
}
System.out.println("Tesseract output: "+resultPlate);
}
}
private static Vector<Rect> detectionPlateCharacterContour(Mat roi) {
Mat contHierarchy = new Mat();
Mat imageMat = roi.clone();
Rect rect = null;
List<MatOfPoint> contours = new ArrayList<>();
Imgproc.findContours(imageMat, contours, contHierarchy, Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_NONE);
Vector<Rect> rect_array = new Vector<>();
for (int i = 0; i < contours.size(); i++) {
rect = Imgproc.boundingRect(contours.get(i));
double ratio = 0;
if(rect.height > rect.width){
ratio = rect.height/rect.width;
}else{
ratio = rect.width/rect.height;
}
Logger.printMessage("Ratio of letter: "+ratio);
double contourarea = Imgproc.contourArea(contours.get(i));
if (contourarea >= 100 && contourarea <= 1000 && ( ratio >= 1 && ratio <= 2)) {
Imgproc.rectangle(roiColor, rect.br(), rect.tl(), new Scalar(255,0,0));
rect_array.add(rect);
}
}
contHierarchy.release();
return rect_array;
}

how to use opencv to calculate HSV histogram in java platform?

Actually, i want to find out the dominant colour in the image, so i want to find the HSV histogram of the image and hence filter out the other colours. However, i dont know how to do this in java platform using opence. I only find the code in C++. Thank you.
Mat image = Highgui.imread("binary07.jpg");
//Mat src = new Mat(image.height(), image.width(), CvType.CV_8UC2);
Imgproc.cvtColor(image, image, Imgproc.COLOR_RGB2GRAY);
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 = false;
Mat h_hist = new Mat();
Mat s_hist = new Mat();
Mat v_hist = new Mat();
//error appear in the following sentences
Imgproc.calcHist((List<Mat>) hsv_planes.get(0), new MatOfInt(3), new Mat(), h_hist, histSize, histRange, accumulate);
Imgproc.calcHist((List<Mat>) hsv_planes.get(1), new MatOfInt(3), new Mat(), s_hist, histSize, histRange, accumulate);
Imgproc.calcHist((List<Mat>) hsv_planes.get(2), new MatOfInt(3), new Mat(), v_hist, histSize, histRange, accumulate);
int hist_w = 512;
int hist_h = 600;
long bin_w = Math.round((double) hist_w / 256);
//bin_w = Math.round((double) (hist_w / 256));
Mat histImage = new Mat(hist_h, hist_w, CvType.CV_8UC1);
Core.normalize(h_hist, h_hist, 3, histImage.rows(), Core.NORM_MINMAX);
Core.normalize(s_hist, s_hist, 3, histImage.rows(), Core.NORM_MINMAX);
Core.normalize(v_hist, v_hist, 3, histImage.rows(), Core.NORM_MINMAX);
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, new Scalar(255, 0, 0), 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, new Scalar(0, 255, 0), 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, new Scalar(0, 0, 255), 2, 8, 0);
}
Highgui.imwrite("histogram.jpg", histImage);
I dont know how to get the output after the split function.
reference:
http://docs.opencv.org/java/
http://docs.opencv.org/doc/tutorials/imgproc/histograms/histogram_calculation/histogram_calculation.html
In the code, the color conversion:
Imgproc.cvtColor(image, image, Imgproc.COLOR_RGB2GRAY);
should be to HSV not gray:
Imgproc.cvtColor(image, image, Imgproc.COLOR_BGR2HSV);
In your example you will only have one (gray) plane instead of the 3 HSV channels. That will give errors when you access the 2nd and 3rd plane.
Here is the code for comparing the histogram of Source image to a reference image for OpenCV 2.4.11 Java (Android).
// Assume SourceImage is a Bitmap ARGB_8888
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
Bitmap refImage = BitmapFactory.decodeFile(mBaseDir + "some_reference.jpg", options);
Mat hsvRef = new Mat();
Mat hsvSource = new Mat();
Mat srcRef = new Mat(refImage.getHeight(), refImage.getWidth(), CvType.CV_8U, new Scalar(4));
Utils.bitmapToMat(refImage, srcRef);
Mat srcSource = new Mat(SourceImage.getHeight(), SourceImage.getWidth(), CvType.CV_8U, new Scalar(4));
Utils.bitmapToMat(SourceImage, srcSource);
/// Convert to HSV
Imgproc.cvtColor(srcRef, hsvRef, Imgproc.COLOR_BGR2HSV);
Imgproc.cvtColor(srcSource, hsvSource, Imgproc.COLOR_BGR2HSV);
/// Using 50 bins for hue and 60 for saturation
int hBins = 50;
int sBins = 60;
MatOfInt histSize = new MatOfInt( hBins, sBins);
// hue varies from 0 to 179, saturation from 0 to 255
MatOfFloat ranges = new MatOfFloat( 0f,180f,0f,256f );
// we compute the histogram from the 0-th and 1-st channels
MatOfInt channels = new MatOfInt(0, 1);
Mat histRef = new Mat();
Mat histSource = new Mat();
ArrayList<Mat> histImages=new ArrayList<Mat>();
histImages.add(hsvRef);
Imgproc.calcHist(histImages,
channels,
new Mat(),
histRef,
histSize,
ranges,
false);
Core.normalize(histRef,
histRef,
0,
1,
Core.NORM_MINMAX,
-1,
new Mat());
histImages=new ArrayList<Mat>();
histImages.add(hsvSource);
Imgproc.calcHist(histImages,
channels,
new Mat(),
histSource,
histSize,
ranges,
false);
Core.normalize(histSource,
histSource,
0,
1,
Core.NORM_MINMAX,
-1,
new Mat());
double resp1 = Imgproc.compareHist(histRef, histSource, 0);
double resp2 = Imgproc.compareHist(histRef, histSource, 1);
double resp3 = Imgproc.compareHist(histRef, histSource, 2);
double resp4 = Imgproc.compareHist(histRef, histSource, 3);
The next code works fine for one depth channel. You have to do just a few modifications to add the other two channels
//Calculate histogram
java.util.List<Mat> matList = new LinkedList<Mat>();
matList.add(imageIR_gray);
Mat histogram = new Mat();
MatOfFloat ranges=new MatOfFloat(0,256);
MatOfInt histSize = new MatOfInt(255);
Imgproc.calcHist(
matList,
new MatOfInt(0),
new Mat(),
histogram ,
histSize ,
ranges);
// Create space for histogram image
Mat histImage = Mat.zeros( 100, (int)histSize.get(0, 0)[0], CvType.CV_8UC1);
// Normalize histogram
Core.normalize(histogram, histogram, 1, histImage.rows() , Core.NORM_MINMAX, -1, new Mat() );
// Draw lines for histogram points
for( int i = 0; i < (int)histSize.get(0, 0)[0]; i++ )
{
Core.line(
histImage,
new org.opencv.core.Point( i, histImage.rows() ),
new org.opencv.core.Point( i, histImage.rows()-Math.round( histogram.get(i,0)[0] )) ,
new Scalar( 255, 255, 255),
1, 8, 0 );
}

Categories