可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I'm trying to access Pixel by Pixel of an IplImage. Im using Java and Processing, and sometimes I need to access pixel by pixel. I've done this so far, but I don't know what's wrong:
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]))); } } }
After Karlphilip sugestion, I came to this, still doens't work. When I try to show, it gives me a nullPointer exception:
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);
回答1:
The fastest way to iterate over each pixel in JavaCV is:
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); } }
回答2:
The following code loads an image from the disk and performs a grayscale conversion by iterating over the pixels of the image:
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);
Not sure if creating a new CvMat
is the best approach, but it's the only way I know to work in javacv.
EDIT:
Unfortunately you use data types that are not from OpenCV, like PImage
, but I did my best to simulate what you are doing.
// 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);