How to save (cvWrite or imwrite) an image in OpenCV 2.4.3? - opencv

I am trying to save an OpenCV image to the hard drive.
Here is what I tried:
public void SaveImage (Mat mat) {
Mat mIntermediateMat = new Mat();
Imgproc.cvtColor(mRgba, mIntermediateMat, Imgproc.COLOR_RGBA2BGR, 3);
File path =
Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES);
String filename = "barry.png";
File file = new File(path, filename);
Boolean bool = null;
filename = file.toString();
bool = Highgui.imwrite(filename, mIntermediateMat);
if (bool == true)
Log.d(TAG, "SUCCESS writing image to external storage");
else
Log.d(TAG, "Fail writing image to external storage");
}
}
Can any one show how to save that image with OpenCV 2.4.3?

Your question is a bit confusing, as your question is concerning OpenCV on the desktop, but your code is for Android, and you ask about IplImage, but your posted code is using C++ and Mat. Assuming you're on the desktop using C++, you can do something along the lines of:
cv::Mat image;
std::string image_path;
//load/generate your image and set your output file path/name
//...
//write your Mat to disk as an image
cv::imwrite(image_path, image);
...Or for a more complete example:
void SaveImage(cv::Mat mat)
{
cv::Mat img;
cv::cvtColor(...); //not sure where the variables in your example come from
std::string store_path("..."); //put your output path here
bool write_success = cv::imwrite(store_path, img);
//do your logging...
}
The image format is chosen based on the supplied filename, e.g. if your store_path string was "output_image.png", then imwrite would save it was a PNG image. You can see the list of valid extensions at the OpenCV docs.
One caveat to be aware of when writing images to disk with OpenCV is that the scaling will differ depending on the Mat type; that is, for floats the images are expected to be within the range [0, 1], while for say, unsigned chars they'll be from [0, 256).
For IplImages, I'd advise just switching to use Mat, as the old C-interface is deprecated. You can convert an IplImage to a Mat via cvarrToMat then use the Mat, e.g.
IplImage* oldC0 = cvCreateImage(cvSize(320,240),16,1);
Mat newC = cvarrToMat(oldC0);
//now can use cv::imwrite with newC
alternately, you can convert an IplImage to a Mat just with
Mat newC(oldC0); //where newC is a Mat and oldC0 is your IplImage
Also I just noticed this tutorial at the OpenCV website, which gives you a walk-though on loading and saving images in a (desktop) environment.

Related

Lossing Quality after Compression using Twelvemonkeys in JAVA and highlighters are removed

I am converting a input file (PDF,TIFF) to Output (TIFF) file by using PDFBox (PDF to BufferedImage) and using twelve monkeys for converting Buffered image to Tiff file by resizing using Imagewriter with IIOImage.
File is converting but losing an quality on the image.And after changed the imagetype BufferedImage.TYPE_BYTE_GRAY to BufferedImage.TYPE_BYTE_BINARY my text highlighters on the file lost.
Below is the code used. How to convert the image without losing quality?
I am converting the image file size 1648*2338 with 200 dpi and i wanted to set photometric interpretation to min_is_white but not able to achieve my problem.
File inputFile = new File(inputImagePath);
BufferedImage inputImage = ImageIO.read(inputFile);
final int imageType = BufferedImage.TYPE_BYTE_BINARY;
// creates output image
BufferedImage outputImage = new BufferedImage(scaledWidth, scaledHeight,imageType);
// scales the input image to the output image
Graphics2D g2d = outputImage.createGraphics();
g2d.drawImage(inputImage, 0, 0, scaledWidth, scaledHeight, null);
g2d.dispose();
// writes to output file
final List<Entry> entries =new ArrayList<Entry>();
entries.add(new TIFFEntry(TIFF.TAG_X_RESOLUTION, new Rational(200)));
entries.add(new TIFFEntry(TIFF.TAG_Y_RESOLUTION, new Rational(200)));
entries.add(new TIFFEntry(TIFF.TAG_PHOTOMETRIC_INTERPRETATION, TIFF.TYPE_SHORT, 0));
final IIOMetadata tiffImageMetadata =new TIFFImageMetadata(entries);
ImageWriter writer = ImageIO.getImageWritersByFormatName("tiff").next();
FileImageOutputStream fio = new FileImageOutputStream(new File(outputImagePath));
ImageWriteParam params = writer.getDefaultWriteParam();
params.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
fio.setByteOrder(ByteOrder.LITTLE_ENDIAN);
IIOMetadata metadata = writer.getDefaultImageMetadata(new ImageTypeSpecifier(outputImage), params);
writer.setOutput(fio);
IIOImage iioimage = new IIOImage(outputImage, null, tiffImageMetadata);
writer.write(null, iioimage, params);
fio.close();
writer.dispose();

How to convert Mat to IplImage in Javacv?

Is any one know how i can convert Mat to IplImage ?
to achieve this i have converted Mat to BufferedImage but again not able to find conversion in BufferedImage to IplImage.
is there any way where i can convert Mat to IplImage?
Thanks
I believe you can convert BufferedImage to IplImage as follows.
public static IplImage toIplImage(BufferedImage src) {
Java2DFrameConverter bimConverter = new Java2DFrameConverter();
OpenCVFrameConverter.ToIplImage iplConverter = new OpenCVFrameConverter.ToIplImage();
Frame frame = bimConverter.convert(src);
IplImage img = iplConverter.convert(frame);
IplImage result = img.clone();
img.release();
return result;
}
I got this from this question. Try this for now. I'll check if direct conversion is possible.
UPDATE:
Please have a look at this api docs. I haven't tested the following. Wrote it just now. Please do try and let me know.
public static IplImage toIplImage(Mat src) {
OpenCVFrameConverter.ToIplImage iplConverter = new OpenCVFrameConverter.ToIplImage();
OpenCVFrameConverter.ToMat matConverter = new OpenCVFrameConverter.ToMat();
Frame frame = matConverter.convert(src);
IplImage img = iplConverter.convert(frame);
IplImage result = img.clone();
img.release();
return result;
}

Writing and saving image in OpenCV

I have written a program that captures a frame from an avi format movie and saves it in JPEG format in the C:\ Directory. I don't get any error when I run my program but when I go to the C:\ directory to find the JPEG file, the file is not even there.
What have I done wrong? I get the same problem while writing a video file in avi format. I just can't find the file in the directory.
here is my code
using namespace std;
using namespace cv;
int main()
{
VideoCapture cap("C:\\airbus.avi");
cap.set(CV_CAP_PROP_POS_FRAMES,200);
Mat img;
cap >> img;
vector<int> compression_params;
compression_params.push_back(CV_IMWRITE_JPEG_QUALITY);
compression_params.push_back(100);
bool bSuccess = imwrite("C:/hello.jpg",img,compression_params);
if (!bSuccess)
{
cout<<"Couldn't save the file"<<endl;
}
else
{
namedWindow("Open",CV_WINDOW_AUTOSIZE);
Mat openImage = imread("C:\\hello.jpg",CV_LOAD_IMAGE_UNCHANGED);
imshow("Open",openImage);
}
waitKey(0);
return 0;
}

How to load ClassifierCascade in Android using JavaCV?

I'm trying to use facial recognition with Android . All the loads are ok , but the haarcascade_frontalface_alt2.xml file wich i don't know how to load it using JavaCV.
This is the code i have:
public static void detectFacialFeatures()
{
// The cascade definition to be used for detection.
// This will redirect the OpenCV errors to the Java console to give you
// feedback about any problems that may occur.
new JavaCvErrorCallback();
// Load the original image.
// We need a grayscale image in order to do the recognition, so we
// create a new image of the same size as the original one.
IplImage grayImage = IplImage.create(iplImage.width(),iplImage.height(), IPL_DEPTH_8U, 1);
// We convert the original image to grayscale.
cvCvtColor(iplImage, grayImage, CV_BGR2GRAY);
CvMemStorage storage = CvMemStorage.create();
// We instantiate a classifier cascade to be used for detection, using the cascade definition.
CvHaarClassifierCascade cascade = new CvHaarClassifierCascade(cvLoad("./haarcascade_frontalface_alt2.xml"));
// We detect the faces.
CvSeq faces = cvHaarDetectObjects(grayImage, cascade, storage, 1.1, 1, 0);
Log.d("CARAS","Hay "+faces.total()+" caras ahora mismo");
}
The problem is here
CvHaarClassifierCascade(cvLoad("./haarcascade_frontalface_alt2.xml"));
I have tried putting the xml file it into the /assets folder , but i have no idea of how must i load it. It's always giving me the next error:
03-26 17:31:25.385: E/cv::error()(14787): OpenCV Error: Null pointer (Invalid classifier cascade) in CvSeq* cvHaarDetectObjectsForROC(const CvArr*, CvHaarClassifierCascade*, CvMemStorage*, std::vector<int>&, std::vector<double>&, double, int, int, CvSize, CvSize, bool), file /home/saudet/projects/cppjars/OpenCV-2.4.4/modules/objdetect/src/haar.cpp, line 1514
...
looking more near at the error it points to this code line:
CvSeq faces = cvHaarDetectObjects(grayImage, cascade, storage, 1.1, 1,
0);
That's why i'm pretty sure that the problem comes from the haarcascade_frontalface_alt2.xml load.
Thanks for your help.
P.D: I want to include the cascade into the apk not in sdcard .
If your cascade is in SD card you can use:
CascadeClassifier cascade = new CascadeClassifier(Environment.getExternalStorageDirectory().getAbsolutePath() + "/cascade.xml");
Environment.getExternalStorageDirectory().getAbsolutePath() give you right path to SD card and next - is address to your file in your SD.
You can pack your file in apk and then copy it to external location so it is accessible by OpenCV functions.
try {
File learnedInputFile = new File(Environment.getExternalStorageDirectory().getPath() + "/learnedData.xml");
if (!learnedInputFile.exists()) {
InputStream learnedDataInputStream = assetManager.open("learnedData.xml");
FileOutputStream learnedDataOutputStream = new FileOutputStream(learnedInputFile);
// copy file from asset folder to external location, i.e. sdcard
byte[] buffer = new byte[300];
int n = 0;
while (-1 != (n = learnedDataInputStream.read(buffer))) {
learnedDataOutputStream.write(buffer, 0, n);
}
}
classifier.load(learnedInputFile.getAbsolutePath());
} catch (IOException exception) {
// there are no learned data, train ml algorithm or show error, etc.
}

detector->detect(img, keypoint); error

I want to implement bag of words in opencv. after detector->detect(img, keypoint); detects keypoints, when i want to clean keypoints using keypoint.clear(); or when the function wants to return the following error will be appeared.
"Unhandled exception at 0x011f45bb in BOW.exe: 0xC0000005: Access violation reading location 0x42ebe098."
and also detected keypoints have bizarre points coordinates like cv::Point_ pt{x=-1.5883997e+038y=-1.5883997e+038 }
Part of the code
Ptr<DescriptorMatcher> matcher = DescriptorMatcher::create("FlannBased");
Ptr<DescriptorExtractor> extractor = new SurfDescriptorExtractor();
Ptr<FeatureDetector> detector = new SurfFeatureDetector(2000);
void extractTrainingVocabulary() {
IplImage *img;
int i,j;
CvSeq *imageKeypoints = 0;
for(j=1;j<=60;j++)
for(i=1;i<=60;i++){
sprintf( ch,"%d%s%d%s",j," (",i,").jpg");
const char* imageName = ch;
Mat img = imread(ch);
vector<KeyPoint> keypoint;
detector->detect(img, keypoint);
Mat features;
extractor->compute(img, keypoint, features);
bowTrainer.add(features);
keypoint.clear();//problem
}
return;
}
I noticed something about your code, on extractTrainingVocabulary() you declare IplImage* img; and inside the loop you declare another variable with the same name (but different type): Mat img = imread(ch);.
Even though that might not be the problem, it's certainly not good practice. I would fix that immediately and update the code on your question.

Resources