Я новичок в обработке изображений с opencv. Я знаю Java, и я пытаюсь удалить фон из изображения. Я собрал некоторый код из интернета и попытался собрать его вместе, и результаты довольно хорошие, но я что-то упустил.
public class RemoveBackground {
public static void main(String[] args) {
// Loading the OpenCV core library
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
// Reading the Image from the file and storing it in to a Matrix object
String file = "C:\\Users\\KobitPC\\Desktop\\Test Pictures/orange.jpg";
Mat man = Imgcodecs.imread(file);
man = doCanny(man);
Imgcodecs.imwrite("C:\\Users\\KobitPC\\Desktop\\Test Pictures/cany.jpg", man);
System.out.println("Image doCanny");
man = doBackgroundRemoval(man);
Imgcodecs.imwrite("C:\\Users\\KobitPC\\Desktop\\Test Pictures/bgremoved.png", man);
System.out.println("Image backgroundRemoval");
}
private static Mat doCanny(Mat frame) {
double threshold = 0;
// init
Mat grayImage = new Mat();
Mat detectedEdges = new Mat();
// convert to grayscale
Imgproc.cvtColor(frame, grayImage, Imgproc.COLOR_BGR2GRAY);
// reduce noise with a 3x3 kernel
Imgproc.blur(grayImage, detectedEdges, new Size(3, 3));
// canny detector, with ratio of lower:upper threshold of 3:1
Imgproc.Canny(detectedEdges, detectedEdges, threshold, threshold * 3, 3, false);
// using Canny's output as a mask, display the result
Mat dest = new Mat();
Core.add(dest, Scalar.all(0), dest);
frame.copyTo(dest, detectedEdges);
return dest;
}
/**
* Perform the operations needed for removing a uniform background
*
* @param frame the current frame
* @return an image with only foreground objects
*/
private static Mat doBackgroundRemoval(Mat frame) {
// init
Mat hsvImg = new Mat();
List<Mat> hsvPlanes = new ArrayList<>();
Mat thresholdImg = new Mat();
// threshold the image with the histogram average value
hsvImg.create(frame.size(), CvType.CV_8U);
Imgproc.cvtColor(frame, hsvImg, Imgproc.COLOR_BGR2HSV);
Core.split(hsvImg, hsvPlanes);
double threshValue = getHistAverage(hsvImg, hsvPlanes.get(0));
Imgproc.threshold(hsvPlanes.get(0), thresholdImg, threshValue, 179.0, Imgproc.THRESH_BINARY_INV);
// Imgproc.threshold(hsvPlanes.get(0), thresholdImg, threshValue, 179.0, Imgproc.THRESH_BINARY);
Imgproc.blur(thresholdImg, thresholdImg, new Size(5, 5));
// dilate to fill gaps, erode to smooth edges
Imgproc.dilate(thresholdImg, thresholdImg, new Mat(), new Point(-1, 1), 6);
Imgproc.erode(thresholdImg, thresholdImg, new Mat(), new Point(-1, 1), 6);
Imgproc.threshold(thresholdImg, thresholdImg, threshValue, 179.0, Imgproc.THRESH_BINARY);
// create the new image
Mat foreground = new Mat(frame.size(), CvType.CV_8UC3, new Scalar(255, 255, 255));
frame.copyTo(foreground, thresholdImg);
return foreground;
}
/**
* Get the average value of the histogram representing the image Hue
* component
*
* @param hsvImg
* the current frame in HSV
* @param hueValues
* the Hue component of the current frame
* @return the average value
*/
private static double getHistAverage(Mat hsvImg, Mat hueValues) {
// init
double average = 0.0;
Mat hist_hue = new Mat();
MatOfInt histSize = new MatOfInt(180);
List<Mat> hue = new ArrayList<>();
hue.add(hueValues);
// compute the histogram
Imgproc.calcHist(hue, new MatOfInt(0), new Mat(), hist_hue, histSize, new MatOfFloat(0, 179));
// get the average for each bin
for (int h = 0; h < 180; h++)
{
average += (hist_hue.get(h, 0)[0] * h);
}
return average = average / hsvImg.size().height / hsvImg.size().width;
}
}
Входное изображение
Выходное изображение
Форма футболки очень хорошо обрезана, но я не понимаю, почему футболка содержит эти линии. Я знаю, что есть способ удалить их и получить чистое изображение без фона.