I have looked through the source code of Matlab Canny edge detection and I managed to write it in Java with OpenCV 3.
private static Mat getpartialedge(Mat image){
double nonEdgeRate = 0.6;
double thresholdRate = 0.6;
double w = image.cols();
double h = image.rows();
int bins = 256;
Mat sobel = new Mat();
Mat sobelx = new Mat();
Mat sobely = new Mat();
Mat sobelxabs = new Mat();
Mat sobelyabs = new Mat();
Size gsz = new Size(5, 5);
if(false) {
Imgproc.Canny(image, sobel, 41, 71);
}else {
//Imgproc.GaussianBlur(graycopy,graycopy, gsz, 2);
//Imgproc.dilate(image, image, kernel8);
Imgproc.GaussianBlur(image, image, gsz, 2);
int apertureSize = 3;
Imgproc.Sobel(image, sobelx, CvType.CV_16S, 1, 0, apertureSize, 1, 0);
Core.convertScaleAbs(sobelx, sobelxabs);
Imgproc.Sobel(image, sobely, CvType.CV_16S, 0, 1, apertureSize, 1, 0);
Core.convertScaleAbs(sobely, sobelyabs);
Core.addWeighted(sobelxabs, 1, sobelyabs, 1, 0, sobel);
sobel.convertTo(sobel, CvType.CV_8U);
Mat equalized = new Mat();
Imgproc.equalizeHist(sobel, equalized);
Imgcodecs.imwrite(filePath + "aftersobel(eq).png", equalized);
Imgcodecs.imwrite(filePath + "aftersobel.png", sobel);
Mat hist = new Mat();
List<Mat> matList = new ArrayList<Mat>();
matList.add(sobel);
Imgproc.calcHist(matList, new MatOfInt(0), new Mat(), hist, new MatOfInt(bins), new MatOfFloat(0f, 256f));
float accu = 0;
float t = (float) (nonEdgeRate * w * h);
float bon = 0;
float[] accutemp = new float[bins];
for (int i = 0; i < bins; i++) {
float tf[] = new float[1];
hist.get(i, 0, tf);
accu = accu + tf[0];
accutemp[i] = accu;
if (accu > t) {
bon = (float) i;
break;
}
}
Imgproc.threshold(sobel, sobel, bon, 255, Imgproc.THRESH_BINARY);
double ut = bon;
double lt = thresholdRate * bon;
Imgproc.Canny(image, sobel, lt, ut);
//Imgproc.dilate(sobel, sobel, kernel2);
}
return sobel;
}
The filepath is the place to hold the output images. And the input image should be a gray-scale image with U8 data type.
The basic principle is to rule out nonEdgeRate(60%) pixel as non-edge pixel by the brightness. A histogram is used to sort the brightness and the upper threshold will be set so that there are 60% pixels below it. The lower threshold is set by multiplying the upper threshold by the thresholdRate(0.6).
Note that the double nonEdgeRate = 0.6 and double thresholdRate = 0.6 is tuned by myself in my specific use case. Th original values are 0.7 and 0.4 separately in matlab.