For a class project, we were required to take a program that implements the Sobel algorithm and run it across multiple threads as an exercise to become familiar with threading. I have the program running correctly as far as threads go (as far as I can tell), however whenever I implement it using more than 1 thread, I see a black border running down the dividing area where the buffer doesn't seem to be writing to the destination BufferedImage.
Here is some code of the method responsible for threading and writing the file:
public void processImage(int threads)
{
try{
File imgFile = new File(bmpFile);
image = ImageIO.read(imgFile);
w = image.getWidth();
wThr = (image.getWidth()/threads);
h = image.getHeight();
inData = new int[wThr*h];
BufferedImage[] pieces = new BufferedImage[threads];
//instantiate array used for storing pieces of image
for (int i=0; i<threads; i++){
pieces[i] = new BufferedImage(wThr, h, BufferedImage.TYPE_BYTE_GRAY);
}
wThr = pieces[0].getWidth();
h = pieces[0].getHeight();
//instantiate target image
combined = new BufferedImage(w, h, BufferedImage.TYPE_BYTE_GRAY);
//split into threads, each one taking a division of the image and running algorithm
Thread[] threadList = new Thread[threads];
for (int i = 0; i < threadList.length; i++) {
image.getRaster().getPixels((i*wThr), 0, wThr, h, inData);
threadList[i] = new Pr1();
threadList[i].start();
try{
threadList[i].join();
}catch (InterruptedException ie) {}
//Write images to pieces and draw pieces individually onto target image
pieces[i].getRaster().setPixels(0, 0, wThr, h, outData);
Graphics2D g = combined.createGraphics();
g.drawImage(pieces[i], i*(wThr), 0, null);
g.dispose();
}
outFile = new File("1.bmp");
ImageIO.write(combined, "BMP", outFile);
}
catch(IOException e)
{
// Handle the exception here!
}
}
This is the image when processed with 2 threads: http://i.imgur.com/n5gasAW.png?1
Anyone have any insight on how to repair this? I've altered the parameters of the BufferedImages and arrays every way I can think and still no luck.
Related
Following this tutorial from openCV, and it should be straight forward. However, it crashes with an assertion fail on the net.forward, that I cannot resolve/find anywhere else.
Thought this problem seemed similar and tried to go through the fix/problem finding. However, restarting the discussion and trials showed it is likely not the same. I used initially 3.4.3, which did not support the same Mat type somehow. Updated to 3.4.7 now, and can confirm the blob size is okay (generated from image). Tried also various other prototxt and caffemodels, but doubt by now that the problem lies there (works if the files are okay, otherwise the net loading fails). The key code should be this:
// Load a network.
public void onCameraViewStarted(int width, int height) {
String proto = getPath("deploy.prototxt", this);
String weights = getPath("MobileNetSSD_deploy.caffemodel", this);
net = Dnn.readNetFromCaffe(proto, weights);
Log.i(TAG, "Network loaded successfully");
}
public Mat onCameraFrame(CvCameraViewFrame inputFrame) {
// Get a new frame
Mat frame = inputFrame.rgba();
Imgproc.cvtColor(frame, frame, Imgproc.COLOR_RGBA2RGB);
// Forward image through network.
Mat blob = Dnn.blobFromImage(frame, 0.007843,
new Size(300, 300),
new Scalar(127.5, 127.5, 127.5));
net.setInput(blob);
Mat detections = net.forward(); //***215 ASSERTION FAILED occurs***
int cols = frame.cols();
int rows = frame.rows();
detections = detections.reshape(1, (int)detections.total() / 7);
for (int i = 0; i < detections.rows(); ++i) {
double confidence = detections.get(i, 2)[0];
if (confidence > 0.2) {
int classId = (int)detections.get(i, 1)[0];
int left = (int)(detections.get(i, 3)[0] * cols);
int top = (int)(detections.get(i, 4)[0] * rows);
int right = (int)(detections.get(i, 5)[0] * cols);
int bottom = (int)(detections.get(i, 6)[0] * rows);
// Draw rectangle around detected object.
Imgproc.rectangle(frame, new Point(left, top), new Point(right, bottom),
new Scalar(0, 255, 0));
String label = classNames[classId] + ": " + confidence;
int[] baseLine = new int[1];
Size labelSize = Imgproc.getTextSize(label, Core.FONT_HERSHEY_SIMPLEX, 0.5, 1, baseLine);
// Draw background for label.
Imgproc.rectangle(frame, new Point(left, top - labelSize.height),
new Point(left + labelSize.width, top + baseLine[0]),
new Scalar(255, 255, 255), Core.FILLED);
// Write class name and confidence.
Imgproc.putText(frame, label, new Point(left, top),
Core.FONT_HERSHEY_SIMPLEX, 0.5, new Scalar(0, 0, 0));
}
}
return frame;
}
public void onCameraViewStopped() {}
// Upload file to storage and return a path.
private static String getPath(String file, Context context) {
AssetManager assetManager = context.getAssets();
BufferedInputStream inputStream = null;
try {
// Read data from assets.
inputStream = new BufferedInputStream(assetManager.open(file));
byte[] data = new byte[inputStream.available()];
inputStream.read(data);
inputStream.close();
// Create copy file in storage.
File outFile = new File(context.getFilesDir(), file);
FileOutputStream os = new FileOutputStream(outFile);
os.write(data);
os.close();
// Return a path to file which may be read in common way.
return outFile.getAbsolutePath();
} catch (IOException ex) {
Log.i(TAG, "Failed to upload a file");
}
return "";
}
The full error message is
cv::Exception: OpenCV(3.4.7) /build/3_4_pack-android/opencv/modules/dnn/src/layers/batch_norm_layer.cpp:39: error: (-215:Assertion failed) blobs.size() >= 2 in function 'cv::dnn::BatchNormLayerImpl::BatchNormLayerImpl(const cv::dnn::experimental_dnn_34_v13::LayerParams&)'
I expect it to not crash. The frame should be okay (image loaded), the net is not empty, and the layers in the net seem fine too (checked since there are some differences using caffe in java). Any help is appreciated!
After some days of research in different directions, I found the problem: the frame format should be BGR, not RGB! That means
Imgproc.cvtColor(frame, frame, Imgproc.COLOR_RGBA2BGR);
I'm using a piece of code to grab a screenshot of my application screen for a group project. On my Macbook Pro the code freezes the screen whereas on my teammates's PC's (all Windows) it runs just fine and exports a .png file in their root dir.
The code
public void screenShot(){
//Creating an rbg array of total pixels
int[] pixels = new int[WIDTH * HEIGHT];
int bindex;
// allocate space for RBG pixels
ByteBuffer fb = ByteBuffer.allocateDirect(WIDTH * HEIGHT * 3);
// grab a copy of the current frame contents as RGB
glReadPixels(0, 0, WIDTH, HEIGHT, GL_RGB, GL_UNSIGNED_BYTE, fb);
// convert RGB data in ByteBuffer to integer array
for (int i=0; i < pixels.length; i++) {
bindex = i * 3;
pixels[i] =
((fb.get(bindex) << 16)) +
((fb.get(bindex+1) << 8)) +
((fb.get(bindex+2) << 0));
}
//Allocate colored pixel to buffered Image
BufferedImage imageIn = null;
try{
//THIS LINE
imageIn = new BufferedImage(WIDTH, HEIGHT,BufferedImage.TYPE_INT_RGB);
//THIS LINE ^^^^^
imageIn.setRGB(0, 0, WIDTH, HEIGHT, pixels, 0 , WIDTH);
} catch (Exception e) {
e.printStackTrace();
}
The problem
When debugging I can see that when stepping in at this line
imageIn = new BufferedImage(WIDTH, HEIGHT,BufferedImage.TYPE_INT_RGB);
the debugger doesn't go to the BufferedImage constructor but to GLFWKeyCallbackI.callback() and after that to GLFWCursorEnterCallbackI.callback(). After this it stops altogether.
What I tried
In my main class above all the rest of the code making a buffered Image as such:
BufferedImage imageIn = new BufferedImage(100,100,BufferedImage.TYPE_INT_RGB);
It also freezes the simulation but it does seems to actually execute the line.
I'm not sure what else I could try, I saw a few other posts ranging between 2005 and today asking similar Mac questions without an answer.
I delved a bit deeper and discovered the issue. As mentioned in a comment here if I provide this VM option "-Djava.awt.headless=true" it seems to fix the issue.
I am trying to extract all the frames of an animated gif to an array of bufferedimages. I have been reading Convert each animated GIF frame to a separate BufferedImage and it was fairly easy to write each frame to a seperate file. But my problem comes up when I try to fill an ArrayList with the frames instead of writing them. Every image in the ArrayList is just the last frame of the gif.
To make it more clear, this code will write each frame to seperate files perfectly:
ArrayList<BufferedImage> frames = new ArrayList<BufferedImage>();
BufferedImage master = new BufferedImage(128, 128, BufferedImage.TYPE_INT_ARGB);
ImageReader ir = new GIFImageReader(new GIFImageReaderSpi());
ir.setInput(ImageIO.createImageInputStream(gif));
for (int i = 0; i < ir.getNumImages(true); i++)
{
master.getGraphics().drawImage(ir.read(i), 0, 0, null);
ImageIO.write(master, "gif", new File(dirGifs + "/frames" + i + ".gif"));
}
However, this code will only gives me an ArrayList full of the same frame (being the last frame of the gif)
ArrayList<BufferedImage> frames = new ArrayList<BufferedImage>();
BufferedImage master = new BufferedImage(128, 128, BufferedImage.TYPE_INT_ARGB);
ImageReader ir = new GIFImageReader(new GIFImageReaderSpi());
ir.setInput(ImageIO.createImageInputStream(gif));
for (int i = 0; i < ir.getNumImages(true); i++)
{
master.getGraphics().drawImage(ir.read(i), 0, 0, null);
frames.add(master);
}
I thought that it was because I wasnt disposing of the graphics afterwards, but I tried creating a graphics object and disposing it and nothing changed. Need help!
It's because the BufferedImage master is being stored in the ArrayList as a reference and not as a copy. So each element of the ArrayList points to the same BufferedImage. I think the easiest way to solve this is just to put the line BufferedImage master = new BufferedImage(128, 128, BufferedImage.TYPE_INT_ARGB); inside the for loop, so a new instance of BufferedImage is created on each iteration.
Colouredmirrorball pointed out that I could solve this problem by creating a new instance of the bufferedimage. So I created a new instance for each array element first and then set the element's data to the same as the master image. The following piece of code gives me an array of frames extracted from an animated gif file.
public ArrayList<BufferedImage> getFrames(File gif) throws IOException {
ArrayList<BufferedImage> frames = new ArrayList<BufferedImage>();
BufferedImage master = new BufferedImage(128, 128, BufferedImage.TYPE_INT_ARGB);
ImageReader ir = new GIFImageReader(new GIFImageReaderSpi());
ir.setInput(ImageIO.createImageInputStream(gif));
for (int i = 0; i < ir.getNumImages(true); i++) {
frames.add(new BufferedImage(128, 128, BufferedImage.TYPE_INT_ARGB));
master.getGraphics().drawImage(ir.read(i), 0, 0, null);
frames.get(i).setData(master.getData());
}
return frames;
}
I am working with Java and combine two images. I save the combined image and want to delete the overlay, but it seems there are still streams open. And i don't know which and how to close them.
f_overlay and f_image are both Files.
// load source images
BufferedImage image = null;
BufferedImage overlay = null;
try {
log.debug(f_image.getAbsolutePath());
log.debug(f_overlay.getAbsolutePath());
image = ImageIO.read(f_image);
overlay = ImageIO.read(f_overlay);
} catch (IOException e) {
log.error(e.getMessage());
}
// create the new image, canvas size is the max. of both image sizes
int w = Math.max(image.getWidth(), overlay.getWidth());
int h = Math.max(image.getHeight(), overlay.getHeight());
BufferedImage combined = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
// paint both images, preserving the alpha channels
Graphics g = combined.getGraphics();
g.drawImage(image, 0, 0, null);
g.drawImage(overlay, 0, 0, null);
// Save as new image
try {
ImageIO.write(combined, "PNG", f_image);
} catch (IOException e) {
log.error(e.getMessage());
}
// we can delete the overlay now
log.debug("Delete overlay: " + f_overlay.delete());
Are there any suggestions?
I can't see anything wrong in your code.
However, I would only delete the file f_overlay if the reading was successful. Important, after you call delete() on the file object, you must not use the object for anything else, so best is to assign f_overlay=null
boolean state = f_overlay.delete();
f_overlay=null;
log.debug("Delete ... "+state);
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Convert pdf file to jpg asp.net
public class Pdf2Image {
private Image image;
int length;
public int convertPdf2Image(String pdfname) {
File file = new File(pdfname);
RandomAccessFile raf;
try {
raf = new RandomAccessFile(file, "r");
FileChannel channel = raf.getChannel();
ByteBuffer buf = channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size());
PDFFile pdffile = new PDFFile(buf);
// draw the first page to an image
int num = pdffile.getNumPages();
length=num;
for (int i = 0; i <= num; i++) {
PDFPage page = pdffile.getPage(i);
//get the width and height for the doc at the default zoom
int width = (int) page.getBBox().getWidth();
int height = (int) page.getBBox().getHeight();
Rectangle rect = new Rectangle(0, 0, width, height);
int rotation = page.getRotation();
Rectangle rect1 = rect;
if (rotation == 90 || rotation == 270) {
rect1 = new Rectangle(0, 0, rect.height, rect.width);
}
//generate the image
BufferedImage img = (BufferedImage) page.getImage(
rect.width, rect.height, //width & height
rect1, // clip rect
null, // null for the ImageObserver
true, // fill background with white
true // block until drawing is done
);
ImageIO.write(img, "png", new File("src\\downloadedFiles\\aa" + i + ".png"));
}
} catch (FileNotFoundException e1) {
System.err.println(e1.getLocalizedMessage());
} catch (IOException e) {
System.err.println(e.getLocalizedMessage());
}
return length;
}
public static void main(String[] args) {
Pdf2Image p = new Pdf2Image();
p.convertPdf2Image("src\\downloadedFiles\\todaypdf.pdf");
}
}
I am using this code to convert PDF file to image. It is working fine for most of the PDF's but showing exception for a PDF file. Exception is:
Expected 'xref' at start of table.
Could any one tell me why it is giving such an exception?
There are many malformed PDF files out in the wild and this is most likely one of them.
It is not possible to give a definite answer until seeing the problem PDF file. What I am guessing is that the 'startxref' specifies an absolute position into the PDF where the xref table should be located. The java library is jumping to this position on the file expecting to find the word 'xref' but cannot find it.
http://blog.amyuni.com/?p=1627
One way to fix this would be to load the file into the full version of Acrobat and then save the file. Acrobat will fix the xref offset as mentioned in the link.
There are quite large companies out there generating malformed PDF's that should know better. Adobe lets these files exist because it makes it hard for their PDF competitors to keep up and compete.