我正在做一些图像处理,我想从灰度图像中提取某些像素值。我要提取的像素用具有与灰度图像相同的尺寸的蒙版阵列描述。
使用numpy阵列在Python中很容易完成。示例:
pixels = img[mask != 0]
任何人都可以建议我使用OPENCV数据类型CV :: MAT?
在C 中以有效的方式进行此操作update
我将提供一个更广泛的例子来澄清我的问题。假设我有一个灰度图像,称为 img 具有尺寸(3,4(。我也有一个具有尺寸(3,4(的蒙版数组。我想从 img 阵列中提取值,与 bask 数组中的非零值的位置相对应。如果我们假设 bask 阵列具有4个非零元素,则需要将4个来自 img 数组的元素提取(复制(为一个称为 Pixels <的新数组>的新数组>。
img = np.arange(12).reshape((3,4))
# img = array([[ 0, 1, 2, 3],
# [ 4, 5, 6, 7],
# [ 8, 9, 10, 11]])
mask = np.zeros_like(img)
mask[0:2, 1] = 255
mask[1, 2:4] = 255
# mask = array([[ 0, 255, 0, 0],
# [ 0, 255, 255, 255],
# [ 0, 0, 0, 0]])
pixels = img[mask != 0]
# pixels = array([1, 5, 6, 7])
我想使用CV :: MAT数组在C 中实现相同的功能。我知道这可以使用循环完成,但是如果存在一个循环,我更喜欢一个更有效的(矢量化(解决方案。
您必须遍历所有图像像素。首先,您可以使用蒙版用参考图像创建图像:
srcImage.copyTo(dstImage, mask);
您现在可以创建函数以在像素上做某事:
//Your function
void doSomething(cv::Point3_<uint8_t> &pixel)
{
//... in this example you can change value like this: pixel.x = 255 - x means first color channel
}
现在,当您迭代时,必须检查像素是否等于零。在C 中,您可以通过几种方式迭代:
// .at method:
// Loop over all rows
for (int r = 0; r < dstImage.rows; r++)
{
// Loop over all columns
for (int c = 0; c < dstImage.cols; c++)
{
// Obtain pixel
Point3_<uint8_t> pixel = dstImage.at<Point3_<uint8_t>>(r, c);
// check if values are zero
if (pixel.x !=0 && pixel.y !=0 && pixel.z !=0)
// function
doSomething(pixel);
// set result
dstImage.at<Point3_<uint8_t>>(r, c) = pixel;
}
}
//with pointers
// Get pointer to first pixel
Point3_<uint8_t>* pixel = dstImage.ptr<Point3_<uint8_t>>(0, 0);
const Point3_<uint8_t>* endPixel = pixel + dstImage.cols * dstImage.rows;
// Loop over all pixels
for (; pixel != endPixel; pixel++)
{
// check if values are zero
if (pixel.x !=0 && pixel.y !=0 && pixel.z !=0)
doSomething(*pixel);
}
//forEach - utilizes all the cores to apply any function at every pixel - the fastest way
//define Functor
struct Operator
{
void operator ()(Point3_<uint8_t> &pixel, const int * position) const
{
// check if values are zero
if (pixel.x !=0 && pixel.y !=0 && pixel.z !=0)
doSomething(pixel);
}
};
//execute functor
dstImage.forEach<Point3_<uint8_t>>(Operator());
如果在参考图像中没有零值,则在上面戴上蒙版之前没有零值。如果是,则必须在foreach中迭代蒙版图像。然后,您可以使用const int * position
参数int x = position[0]; int y = position[1];
检查哪些坐标掩码像素等于0,并且仅在参考图像上做某事。