OpenCV Java-更改像素颜色

问题描述 投票:1回答:1

我正在尝试确定将蒙版的像素颜色从黑色更改为其他颜色的方法。不幸的是,我无法确定执行此任务的方法。本质上,我想做的就是拍摄这张图片:mask

并将黑色部分转换为具有值(255、160、130)的颜色。我尝试了几种方法来实现自己的目标。这些包括绘制轮廓,setTo和遍历矩阵。不幸的是,所有这些尝试都失败了。我将代码和结果包括在下面。

绘制轮廓方法

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 );
         }

Draw Contours

注意,我也尝试过使用Imgproc.RETR_EXTERNAL,但这产生了一个全黑的图像。 HighGui窗口的名称也称为“洪水填充”,但我只是忘了更新名称。

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);

setTo

迭代矩阵

   // 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);
            }
        }
    }

iterating over matrix

该循环很有希望,但是我知道它不会很有效,因为我还要更新另外两个掩码。您能否建议一种有效的方法,使我可以为所有三个通道设置值?

谢谢

java opencv
1个回答
0
投票

我不确定为什么要对图像进行许多操作,但是对我来说,这就像应用蒙版并有效地替换颜色。因此,如果还有其他复杂情况,请告诉我。

下面是我在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);
}

我们正在使用mask方法为黑色的0-50之间的像素值创建inRange

Core.inRange(matr, new Scalar(0), new Scalar(50), result);

然后使用mask方法将result变量中的setTo应用于原始矩阵。通过Scalar对象以HSV格式提供替换颜色值。可以在RGB中理解HSV中的新标量(a,b,c),例如Red = c,Green = b和Blue = a。

matr.setTo(new Scalar(130,160,255),result);

与逐个迭代像素相比,它相当快。

© www.soinside.com 2019 - 2024. All rights reserved.