我正在尝试访问IplImage的Pixel by Pixel。我使用Java和Processing,有时我需要逐像素访问。到目前为止我已经这样做了,但我不知道出了什么问题:
public IplImage PImageToIplImage(PImage imageSrc)
{
IplImage imageDst;
if(imageSrc.format==RGB)
{
imageDst = IplImage.create(imageSrc.width, imageSrc.height, IPL_DEPTH_8U, 3);
ByteBuffer imagePixels=imageDst.getByteBuffer();
int locPImage, locIplImage, x, y;
for(y=0; y<imageSrc.height; y++)
for(x=0; x<imageSrc.width; x++)
{
locPImage = x + y * width;
locIplImage=y*imageDst.widthStep()+3*x;
imagePixels.put(locIplImage+2, (byte)(red(imageSrc.pixels[locPImage])));
imagePixels.put(locIplImage+1, (byte)(green(imageSrc.pixels[locPImage])));
imagePixels.put(locIplImage, (byte)(blue(imageSrc.pixels[locPImage])));
}
}
}
Karlphilip消化后,我来到这里,仍然没有工作。当我尝试显示时,它给了我一个nullPointer异常:
imageDst = IplImage.create(imageSrc.width, imageSrc.height, IPL_DEPTH_8U, 3);
CvMat imagePixels = CvMat.createHeader(imageDst.height(), imageDst.width(), CV_32FC1);
cvGetMat(imageDst, imagePixels, null, 0);
int locPImage, x, y;
for(y=0; y<imageSrc.height; y++)
for(x=0; x<imageSrc.width; x++)
{
locPImage = x + y * width;
CvScalar scalar = new CvScalar();
scalar.setVal(0, red(imageSrc.pixels[locPImage]));
scalar.setVal(1, green(imageSrc.pixels[locPImage]));
scalar.setVal(2, blue(imageSrc.pixels[locPImage]));
cvSet2D(imagePixels, y, x, scalar);
}
imageDst = new IplImage(imagePixels);
答案 0 :(得分:7)
迭代JavaCV中每个像素的最快方法是:
ByteBuffer buffer = image.getByteBuffer();
for(int y = 0; y < image.height(); y++) {
for(int x = 0; x < image.width(); x++) {
int index = y * image.widthStep() + x * image.nChannels();
// Used to read the pixel value - the 0xFF is needed to cast from
// an unsigned byte to an int.
int value = buffer.get(index) & 0xFF;
// Sets the pixel to a value (greyscale).
buffer.put(index, value);
// Sets the pixel to a value (RGB, stored in BGR order).
buffer.put(index, blue);
buffer.put(index + 1, green);
buffer.put(index + 2, red);
}
}
答案 1 :(得分:1)
以下代码从磁盘加载图像并通过迭代图像的像素执行灰度转换:
IplImage image = cvLoadImage("pipeline.png", CV_LOAD_IMAGE_COLOR);
if (image == null)
{
System.out.println("Erro ao carregar imagem!");
return;
}
double r, g, b;
r = g = b = 0.0;
CvMat mtx = CvMat.createHeader(image.height(), image.width(), CV_32FC1);
cvGetMat(image, mtx, null, 0);
System.out.println(mtx.rows() + "x" + mtx.cols());
for (int i = 0; i < mtx.rows(); i++)
{
for (int j = 0; j < mtx.cols(); j++)
{
CvScalar rgb = cvGet2D(mtx, i, j);
r = rgb.val(0);
g = rgb.val(2);
b = rgb.val(1);
double gray = (r + g + b) / 3;
CvScalar scalar = new CvScalar();
scalar.setVal(0, gray);
scalar.setVal(1, gray);
scalar.setVal(2, gray);
cvSet2D(mtx, i, j, scalar);
}
}
IplImage result = new IplImage(mtx);
cvSaveImage("manual_gray.png", result);
cvReleaseImage(image);
不确定创建新的CvMat
是否是最好的方法,但这是我知道在javacv中工作的唯一方法。
修改强>:
不幸的是,您使用的数据类型不是来自OpenCV,like PImage
,但我尽力模拟您正在做的事情。
// Create a black image
IplImage imageDst = IplImage.create(imageSrc.width(), imageSrc.height(), IPL_DEPTH_8U, 3);
// Create a temporary mat to iterate over it's pixels
CvMat imagePixels = CvMat.createHeader(imageDst.height(), imageDst.width(), CV_32FC1);
// Copy black image to temporary mat
cvGetMat(imageDst, imagePixels, null, 0);
int x, y;
for(y=0; y<imageSrc.height(); y++)
for(x=0; x<imageSrc.width(); x++)
{
// At this point you tried to do: locPImage = x + y * width;
// but I think you might have mistaken for: locPImage = y + x * width;
//...
}
imageDst = new IplImage(imagePixels);