java - 在 Mat OpenCV Android 中循环和更改像素值

标签 java android opencv image-processing pixel

我现在正在构建一个基于示例颜色 Blob 跟踪方法的项目。我在轮廓周围使用边界矩形来指示 Blob 。现在我想通过使用纠错方法来改进这个算法。我现在所做的只是简单地使用 elemsum 方法对矩形区域中的像素求和并计算平均强度并将其设置为每帧中的新 Blob 检测参数。然而,问题在于它不准确,因为轮廓外但边界矩形内的那些像素也会被计算在内。结果很差。

为了解决这个问题,我使用了另一种直接的方法来循环遍历矩形区域(这是一个子垫)中的每个像素,并将所有超出范围的像素值设置为所需的(或先前的)hsv 标量。然后再次对所有像素求和并计算平均强度。这样会更准确,更容易解决问题。问题是该程序在手机上运行速度太慢(每秒大约 1 帧),但结果是准确的。

我在网上找到了一些关于如何使用 mat.forEach 在 C++ 中执行此操作的资源。我不想做 ndk 的事情,我想知道在 Java (Android) 中是否有更有效的方法来做这件事。

更新: 事实证明,我可以通过简单地降低采样率来解决问题。无需计算所有像素的平均强度,只需几个像素即可完成这项工作。我的代码:

for (int i=0; i< bounding_rect_hsv.rows();i+=10){
                for (int j=0; j<bounding_rect_hsv.cols();j+=10){
                    double[] data = bounding_rect_hsv.get(i, j);
                    for (int k = 0; k < 3; k++){
                        if (data[k] > new_hsvColor.val[k] + 30 || data[k] < new_hsvColor.val[k] - 30) {
                            data[k] = new_hsvColor.val[k];
                        }
                    }
                    bounding_rect_hsv.put(i, j, data); //Puts element back into matrix
                }
            }

我的源代码:

Rect rect = Imgproc.boundingRect(points);

// draw enclosing rectangle (all same color, but you could use variable i to make them unique)
Imgproc.rectangle(original_frame, new Point(rect.x, rect.y), new Point(rect.x + rect.width, rect.y + rect.height), new Scalar(255, 0, 0, 255), 3);

//Todo: use the bounding rectangular to calculate average intensity (turn the pixels out of the contour to new_hsvColor)
//Just change the boundary values would be enough
bounding_rect_rgb = original_frame.submat(rect);
Imgproc.cvtColor(bounding_rect_rgb, bounding_rect_hsv, Imgproc.COLOR_RGB2HSV_FULL);

//Todo: change the logic so that pixels outside the contour will be changed to new_hsvColor

for (int i=0; i< bounding_rect_hsv.rows();i++){
    for (int j=0; j<bounding_rect_hsv.cols();j++){
        double[] data = bounding_rect_hsv.get(i, j);
        for (int k = 0; k < 3; k++){
        if (data[k] > new_hsvColor.val[k] + 30 || data[k] < new_hsvColor.val[k] - 30)
        data[k] = new_hsvColor.val[k];
        }
        bounding_rect_hsv.put(i, j, data); //Puts element back into matrix
    }
}

最佳答案

如果您想计算轮廓内像素的均值值,您可以简单地:

  1. 使用 drawContours 创建一个 mask 使用参数 CV_FILLED 和颜色 Scalar(255) 在黑色 (Scalar(0)) 上初始化 CV_8UC1 图像与原始图片大小相同。
  2. 使用mean计算掩码下像素的平均值。

您也不需要将每个区域(Rect)转换为 HSV,但您可以将整个图像转换一次,然后直接在 HSV 图像上访问所需区域。


在一般情况下,您想要对很多矩形区域的像素值求和,您可能更愿意计算 integral图像并将总和计算为右下角和左上角矩形位置的值之差。

关于java - 在 Mat OpenCV Android 中循环和更改像素值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34490469/

相关文章:

java - 在这种情况下继承和多态性如何工作?

java - 如何使 Jersey Rest POST 请求同步

c++ - 使用 OpenCV 在图像上悬停时打印鼠标指针的像素坐标

android - 如何从相机预览中检测现有图像?

c++ - 将 vector <Mat> 转换为 vector 文件 Opencv

java - FileWriter 不使用 URL 中的协议(protocol)写入文件

java - Eclipse 不一致 : Resource leak: '<unassigned Closeable value>' is never closed

java - gcm_defaultSenderId 无法解析

android - 服务以 START_NOT_STICKY 重新启动

java - 如何在Android POST方法中与body一起使用Retrofit?