我正在尝试确定将蒙版的像素颜色从黑色更改为其他颜色的方法。不幸的是,我无法确定执行此任务的方法。本质上,我想做的就是拍摄这张图片:
,然后将黑色部分转换为具有值(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 );
}
请注意,我也尝试使用Imgproc.RETR_EXTERNAL,但这产生了全黑的图像。 HighGui窗口的名称也称为“洪水填充”,但我只是忘了更新名称。
设置为
// replace find and draw contours portion of code above
Mat out = new Mat();
background.copyTo(out);
out.setTo(new Scalar(255, 160, 130), background);
遍历矩阵
// 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);
}
}
}
这个循环很有希望,但是我知道它不会很有效,因为我还有另外两个要更新的掩码。您能提出一个有效的方法,让我为所有三个通道设置值吗?
谢谢
答案 0 :(得分:1)
我不确定为什么要对图像进行许多操作,但是对我来说,这就像应用蒙版并有效地替换颜色。因此,如果还有其他复杂情况,请告诉我。
下面是我在Java中寻找的代码。
cx = 0;
cy = 0;
for point_number in range(0, number_of_points):
cx = cx + co_ordinates[frame_number][point_number][0][0]
cy = cy + co_ordinates[frame_number][point_number][0][1]
cx = cx / number_of_points;
cy = cy / number_of_points;
if frame_number > 0:
distance = math.sqrt((cx-prevx)**2 + (cy-prevy)**2)
# Calculate speed
prevx = cx;
prevy = cy;
我们正在使用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);
}
方法为黑色的0-50之间的像素值创建一个mask
。
inRange
然后使用Core.inRange(matr, new Scalar(0), new Scalar(50), result);
方法将此mask
变量中的result
应用于原始矩阵。通过setTo
对象以HSV格式提供替换颜色值。可以在RGB中理解HSV中的新标量(a,b,c),例如Red = c,Green = b和Blue = a。
Scalar
与逐个迭代像素相比,它相当快。