Compressing IplImage to JPEG using libjpeg in OpenCV - opencv

So I have this problem. I have an IplImage that i want to compress to JPEG and do something with it. I use libjpeg8b.The code exit when it goes the function of jpeg_start_compress() with an error of "Bogus input colorspace" .Here are my code.
#include "highgui.h"
#include <stdio.h>
#include "jpeglib.h"
#include "cv.h"
#include <iostream>
#include <fstream>
using namespace std;
using namespace cv;
#pragma comment(lib, "jpeglib.lib")
bool ipl2jpeg(IplImage *frame, unsigned char **outbuffer, unsigned long*outlen)
{
IplImage *img = new IplImage;
memcpy(img,frame,frame->nSize);
unsigned char *outdata = (uchar *) img->imageData;
struct jpeg_compress_struct cinfo = {0};
struct jpeg_error_mgr jerr;
JSAMPROW row_ptr[1];
int row_stride;
*outbuffer = NULL;
*outlen = 0;
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_compress(&cinfo);
jpeg_mem_dest(&cinfo, outbuffer, outlen);
cinfo.image_width = frame->width;
cinfo.image_height = frame->height;
cinfo.input_components = frame->nChannels;
cinfo.in_color_space = JCS_RGB;
jpeg_set_defaults(&cinfo);
jpeg_start_compress(&cinfo, TRUE);
system("pause");
row_stride = frame->width * frame->nChannels;
while (cinfo.next_scanline < cinfo.image_height)
{
row_ptr[0] = &outdata[cinfo.next_scanline * row_stride];
jpeg_write_scanlines(&cinfo, row_ptr, 1);
}
jpeg_finish_compress(&cinfo);
jpeg_destroy_compress(&cinfo);
return true;
}
int main()
{
ofstream fout("text.txt");
unsigned char **buf;
buf = new unsigned char* [120];
for(int i=0;i<500;i++)
{
buf[i] = new unsigned char[120];
}
for(int i=0;i< 120;i++)
{
for(int j=0;j<120;j++)
{
buf[i][j] = 0;
}
}
unsigned long *len = new unsigned long;
*len = 120*120;
Ptr<IplImage> img = cvLoadImage("test.jpg",CV_LOAD_IMAGE_GRAYSCALE);
ipl2jpeg(img,buf,len);
for(int i=0;i< 120;i++)
{
for(int j=0;j<120;j++)
{
fout<<buf[i][j]<<endl;
}
}
return 0;
}

I've never used libjpeg before, but it looks like you're mixing color spaces. You load the image as a grayscale (CV_LOAD_IMAGE_GRAYSCALE), but are telling libjpeg that it's an RGB image (JCS_RGB). Have you tried changing the line
cinfo.in_color_space = JCS_RGB;
to
cinfo.in_color_space = JCS_GRAYSCALE;
?

Is there any reason why you're not using opencv's native JPEG support?
cvSaveImage(frame, "frame.jpeg");
The documentation is here.
EDIT
If you insist on using libjpeg, have a look at this post.

Related

Opencv imread a frame

I have recently used this piece of code to save frame data from a webcam
#include <opencv\cv.h>
#include <opencv\highgui.h>
#include <opencv2/opencv.hpp>
using namespace cv;
#include <fstream>
using namespace std;
int main(int argc, char** argv)
{
VideoCapture cap(0); // open the default camera
if (!cap.isOpened()) // check if we succeeded
return -1;
cap.set(CV_CAP_PROP_FPS, 15);
Mat edges;
namedWindow("image", 1);
std::vector<cv::Mat> images(100);
for (int i = 0; i < 100; ++i) {
// this is optional, preallocation so there's no allocation
// during capture
images[i].create(480, 640, CV_8UC3);
}
for (int i = 0; i < 100; ++i)
{
Mat frame;
cap >> frame; // get a new frame from camera
frame.copyTo(images[i]);
}
cap.release();
for (int i = 0; i < 100; ++i)
{
imshow("image", images[i]);
if (waitKey(30) >= 0) break;
}
After this, I want to use imread to analyse the newly splitted frames. However, I cannot think of a way to accomplish this.
I tried: Mat colorImage = imread(images[i]);
However, it leads to:
error C2664: 'cv::Mat cv::imread(const cv::String &,int)': cannot convert argument 1 from 'std::vector<cv::Mat,std::allocator<_Ty>>' to 'const cv::String &'
with
[
_Ty=cv::Mat
]
Thanks a lot in advance :)
imread function is used to open the image from disk.
You already have vector of images so you just do:
Mat colorImage = images[i];
and btw. there is no need for this:
for (int i = 0; i < 100; ++i) {
// this is optional, preallocation so there's no allocation
// during capture
images[i].create(480, 640, CV_8UC3);
}
because you are allocating new space anyway except you capture the frames directly like this:
cap >> images[i];

Why is webcam image processing slow while using Xcode in an OpenCV project?

Why is webcam image processing is very slow while using Xcode for this OpenCV project, and only one out of three windows are working (similar spaces and HSV windows are not turning up) and are very slow? How to increase the speed of execution of the program?
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>
using namespace cv;
using namespace std;
Mat img, hsv, res;
char *win1 = "RGB";
char *win2 = "HSV";
char *win3 = "similar spaces";
uchar thresh = 5;
void setColor(uchar hval){
int i,j;
for (i = 0; i < res.rows; ++i){
for (j = 0; j < res.cols; ++j){
if( hsv.at<Vec3b>(i,j)[0] <= hval+thresh
&& hsv.at<Vec3b>(i,j)[0] >= hval-thresh)
res.at<uchar>(i,j) = 255;
else res.at<uchar>(i,j) = 0;
}
}
imshow(win3, res);
}
void MouseCallBackFunc(int event, int x, int y, int flags, void* userdata){
if(event==EVENT_LBUTTONDOWN){
cout<<"\t x,y : "<<x<<','<<y<<endl;
cout<<'\t'<<img.at<Vec3b>(y,x)<<endl;
setColor(hsv.at<Vec3b>(y,x)[0]);
}
}
int main()
{
img = imread("/usr/share/opencv/samples/cpp/stuff.jpg", CV_LOAD_IMAGE_COLOR);
hsv = Mat::zeros(img.size(), CV_8UC3);
res = Mat::zeros(img.size(), CV_8UC1);
char c;
int i,j;
namedWindow(win2, CV_WINDOW_NORMAL);
namedWindow(win3, CV_WINDOW_NORMAL);
cvtColor(img, hsv, CV_RGB2HSV);
imshow(win1, img);
imshow(win2, hsv);
imshow(win3, res);
setMouseCallback(win1, MouseCallBackFunc, NULL);
// VideoCapture stream(0); //0 is the id of video device.0 if you have only one camera.
// if (!stream.isOpened()) { //check if video device has been initialised
// cout << "cannot open camera";
// }
// while (true) {
// Mat cameraFrame;
// stream.read(cameraFrame);
// imshow("test", cameraFrame);
// c = waitKey(30);
// if(c==27)
// break;
// }
while((c=waitKey(300))!=27){}
return 0;
}

OpenCV create Mat of float from binary

I have a binary Mat (1x256) (CV_8UC1) with 256 bytes. I need to create another Mat (CV_32F) of floats with 1x64 dimension out of it. Meaning that each 4 bytes construct a float value in result matrix.
Is there any way to do that in OpenCV? Or any other C++ way?
#include "opencv2/opencv.hpp"
using namespace cv;
#include <assert.h>
int main()
{
Mat floatOrig = Mat::zeros(1,64,CV_32FC1);
Mat ucharConverted = Mat::zeros(1,256,CV_8UC1);
Mat floatConverted = Mat::zeros(1,64,CV_32FC1);
//construct some data
RNG rng = theRNG();
for(int i=0;i<floatOrig.cols;++i)
{
floatOrig.at<float>(0,i)=rng.gaussian(1.);
}
//save them into uchar first
for(int i=0;i<ucharConverted.cols;++i)
{
ucharConverted.at<uchar>(0,i)= floatOrig.at<uchar>(0,i);
}
//now convert them back into float
//uchar b[4] = {0}; uncomment for big endian data
for(int i=0;i<floatConverted.cols;++i)
{
/* uncomment for big endian ordering
b[0]=ucharConverted.at<uchar>(0,i*4+3);
b[1]=ucharConverted.at<uchar>(0,i*4+2);
b[2]=ucharConverted.at<uchar>(0,i*4+1);
b[3]=ucharConverted.at<uchar>(0,i*4+0);
memcpy(&floatConverted.at<float>(0,i),&b, sizeof(float));
*/
memcpy(&floatConverted.at<float>(0,i),&ucharConverted.at<uchar>(0,i*4), sizeof(float));
}
//verify
for(int i=0;i<floatConverted.cols;++i)
{
assert(floatConverted.at<float>(0,i)-floatOrig.at<float>(0,i)==0.);
}
// now lets try saving that to file
FILE* fp = fopen("c:/data/float64.bin","wb");
for(size_t i=0;i<floatConverted.cols;++i)
{
fwrite( &floatConverted.at<float>(0,i),sizeof(float),1,fp);
}
fclose(fp);
floatConverted=0;//we gonna try to load it back
fp = fopen("c:/data/float64.bin","rb");
for(size_t i=0;i<floatConverted.cols;++i)
{
fread( &floatConverted.at<float>(0,i),sizeof(float),1,fp);
}
fclose(fp);
//verify data read from file
for(int i=0;i<floatConverted.cols;++i)
{
assert(floatConverted.at<float>(0,i)-floatOrig.at<float>(0,i)==0.);
}
getchar();
}

Image Processing Opencv

I am having doubt in opencv. I'm trying to implement SURF algorithm. When I trying to build the code but I'm getting the following error.
*****error LNK2019: unresolved external symbol _cvExtractSURF referenced in function _main
1>SAMPLE.obj : error LNK2019: unresolved external symbol _cvSURFParams referenced in function _main*****
I have gone through all the posts related to my topic in this forum, but couldn't figure out the problem with my code. Please help me in resolving my problem.
code :
#include <stdio.h>
#include <opencv2/features2d/features2d.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc_c.h>
#include <opencv2\objdetect\objdetect.hpp>
#include <opencv2\calib3d\calib3d.hpp>
#include <opencv2\core\core.hpp>
#include <opencv2\legacy\legacy.hpp>
#include <opencv2\legacy\compat.hpp>
#include <opencv2/nonfree/nonfree.hpp>
#include <opencv\opensurf\surf.h>
using namespace cv;
using namespace std;
int main(int argc, char** argv)
{
CvMemStorage* storage = cvCreateMemStorage(0);
cvNamedWindow("Image", 1);
int key = 0;
static CvScalar red_color[] ={0,0,255};
IplImage* capture= cvLoadImage( "testface.jpg");
CvMat* prevgray = 0, *image = 0, *gray =0;
while( key != 'q' )
{
int firstFrame = gray == 0;
IplImage* frame =capture;
if(!frame)
break;
if(!gray)
{
image = cvCreateMat(frame->height, frame->width, CV_8UC1);
}
//Convert the RGB image obtained from camera into Grayscale
cvCvtColor(frame, image, CV_BGR2GRAY);
//Define sequence for storing surf keypoints and descriptors
CvSeq *imageKeypoints = 0, *imageDescriptors = 0;
int i;
//Extract SURF points by initializing parameters
CvSURFParams params = cvSURFParams(500,1);
cvExtractSURF( image, 0, &imageKeypoints, &imageDescriptors, storage, params );
printf("Image Descriptors: %d\n", imageDescriptors->total);
//draw the keypoints on the captured frame
for( i = 0; i < imageKeypoints->total; i++ )
{
CvSURFPoint* r = (CvSURFPoint*)cvGetSeqElem( imageKeypoints, i );
CvPoint center;
int radius;
center.x = cvRound(r->pt.x);
center.y = cvRound(r->pt.y);
radius = cvRound(r->size*1.2/9.*2);
cvCircle( frame, center, radius, red_color[0], 1, 8, 0 );
}
cvShowImage( "Image", frame );
cvWaitKey(0);
}
cvDestroyWindow("Image");
return 0
}
Thank you,
Sreelakshmi Priya

Can you improve this solution to interfacing OpenCV 2.4+ to Zxing 1D barcode reader

I didn't find this solution on the net, had to figure it myself. So, for benefit of others, I'm posing this as a "question":
Can you improve my working interface of OpenCV 2.4+ to the C++ version of Zxing 2.2 1D barcode reader?
Here's my working but perhaps improvable implementation below:
/**
* Gary Bradski, Reading 1D barcodes
* License BSD, (c) 2013
*
* Working example of how to call zxing using OpenCV 2.4+ cv::Mat
*
* Calling example, this one for 128 barcodes:
*
* Code128Reader cr; //Instantiate a zxing barcode reader, int this case for 128 barcodes,
* // but you can use any of their 1D or multi readers here
* ... by magic, I find, rectify and islotate a barcode into cv::Mat barcodeImage
* decode_image(&cr, barcodeImage); //Decode the isolated rectified barcode or fail
*
*/
#include <string>
#include <fstream>
#include <iostream>
#include <vector>
using namespace cv;
using namespace std;
//////////////ZXING BARCODE READER//////////////////////////////////////////
#include <zxing/LuminanceSource.h>
#include <zxing/MultiFormatReader.h>
#include <zxing/oned/OneDReader.h>
#include <zxing/oned/EAN8Reader.h>
#include <zxing/oned/EAN13Reader.h>
#include <zxing/oned/Code128Reader.h>
#include <zxing/datamatrix/DataMatrixReader.h>
#include <zxing/qrcode/QRCodeReader.h>
#include <zxing/aztec/AztecReader.h>
#include <zxing/common/GlobalHistogramBinarizer.h>
#include <zxing/Exception.h>
using namespace zxing;
using namespace oned;
using namespace datamatrix;
using namespace qrcode;
using namespace aztec;
class OpenCVBitmapSource : public LuminanceSource
{
private:
cv::Mat m_pImage;
public:
OpenCVBitmapSource(cv::Mat &image)
: LuminanceSource(image.cols, image.rows)
{
m_pImage = image.clone();
}
~OpenCVBitmapSource(){}
int getWidth() const { return m_pImage.cols; }
int getHeight() const { return m_pImage.rows; }
ArrayRef<char> getRow(int y, ArrayRef<char> row) const //See Zxing Array.h for ArrayRef def
{
int width_ = getWidth();
if (!row)
row = ArrayRef<char>(width_);
const char *p = m_pImage.ptr<char>(y);
for(int x = 0; x<width_; ++x, ++p)
row[x] = *p;
return row;
}
ArrayRef<char> getMatrix() const
{
int width_ = getWidth();
int height_ = getHeight();
ArrayRef<char> matrix = ArrayRef<char>(width_*height_);
for (int y = 0; y < height_; ++y)
{
const char *p = m_pImage.ptr<char>(y);
int yoffset = y*width_;
for(int x = 0; x < width_; ++x, ++p)
{
matrix[yoffset + x] = *p;
}
}
return matrix;
}
/*
// The following methods are not supported by this demo (the DataMatrix Reader doesn't call these methods)
bool isCropSupported() const { return false; }
Ref<LuminanceSource> crop(int left, int top, int width, int height) {}
bool isRotateSupported() const { return false; }
Ref<LuminanceSource> rotateCounterClockwise() {}
*/
};
void decode_image(Reader *reader, cv::Mat &image)
{
try
{
Ref<OpenCVBitmapSource> source(new OpenCVBitmapSource(image));
Ref<Binarizer> binarizer(new GlobalHistogramBinarizer(source));
Ref<BinaryBitmap> bitmap(new BinaryBitmap(binarizer));
Ref<Result> result(reader->decode(bitmap, DecodeHints(DecodeHints::TRYHARDER_HINT)));//+DecodeHints::DEFAULT_HINT)));
cout << result->getText()->getText() << endl;
//Export the read barcode here
}
catch (zxing::Exception& e)
{
//Export your failure to read the code here
cerr << "Error: " << e.what() << endl;
}
}
Forgot to attribute what I started with. There is an out of date (will not compile) implementation using IplImages here:
http://www.idealsoftware.com/opensource/scan-1d-2d-barcodes-webcam-zxing-opencv-visual-c.html
This updates that solution so that it works with Zxing 2.2 and OpenCV 2.1+
I think you can avoid the matrix copy by replacing
Ref<OpenCVBitmapSource> source(new OpenCVBitmapSource(image));
With
Ref<LuminanceSource> source(new GreyscaleLuminanceSource(image.data, image.step, image.rows, 0, 0, image.cols, image.rows));

Resources