Hey, guys, i am using opencv to do some vehicle recognition work, and when i use cvThershold to convert the gray image to binary image, the return image is really strange, the binary image supposes to have only two values,0 and 255, however, it contains other values like 2,3,254,253, anyone knows how this happens, and also cvCmps also has this problem.
cvThreshold has a variety of behaviours beyond normal binary thresholding. They are described in the OpenCV API reference.
For example, if you call it with the flag threshold_type set CV_THRESH_TRUNC, it will truncate all intensities above the specified threshold only. The intensities below the threshold will remain untouched. Perhaps this accounts for your strange result?
If you post the image and your code (the bit that calls cvThreshold is enough) I could probably be of more help.
Try this:
/*
* compile with:
*
* g++ -Wall -ggdb -I. -I/usr/include/opencv -L /usr/lib -lm -lcv -lhighgui -lcvaux threshold.cpp -o threshold.out
*/
#include <cv.h>
#include <highgui.h>
#include <stdio.h>
#include <assert.h>
IplImage *
threshold(IplImage const *in, int threshold)
{
assert(in->nChannels == 1);
CvSize size = cvSize(in->width, in->height);
IplImage *out = cvCreateImage(size, IPL_DEPTH_8U, 1);
cvThreshold(in, out, threshold, 255, CV_THRESH_BINARY);
return out;
}
void
show_image(char const *title, IplImage const *image)
{
cvNamedWindow(title, CV_WINDOW_AUTOSIZE);
cvShowImage(title, image);
cvWaitKey(0);
cvDestroyWindow(title);
}
int
main(int argc, char **argv)
{
if (argc < 2)
{
fprintf(stderr, "usage: %s in.png\n", argv[0]);
return 1;
}
IplImage *in = cvLoadImage(argv[1]);
IplImage *grey = in;
if (in->nChannels != 1)
{
/*
* For some reason, cvCreateImage returns an image with 3 channels even
* when a greyscale image is specified (e.g. PGM). Hack around this by
* just taking the first channel of the image. OpenCV uses BGR order,
* so it will be the B channel.
*/
CvSize size = cvSize(in->width, in->height);
grey = cvCreateImage(size, IPL_DEPTH_8U, 1);
cvSplit(in, grey, NULL, NULL, NULL);
cvReleaseImage(&in);
}
IplImage *thres = threshold(grey, 127);
show_image("thresholded", thres);
cvReleaseImage(&thres);
cvReleaseImage(&grey);
return 0;
}
Give it any image (even a colour one, see comment for clarification), e.g. [this one][1]. Do you get the expected result?
[1]: http://r0k.us/graphics/kodak/kodak/kodim20.png SixShooter
Related
Hi. I have the above image and use the "findContours" function.
And then I use the "convexity defects" functions to find the corner points.
The result is as follows.
The problem with this code is that it can not find the rounded corners.You can not find a point like the following.
This is my code
#include "opencv2/imgcodecs.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/videoio.hpp"
#include <opencv2/highgui.hpp>
#include <opencv2/video.hpp>
#include <iostream>
#include <sstream>
#include <fstream>
using namespace cv;
using namespace std;
int main(int argc, char** argv)
{
cv::Mat image = cv::imread("find_Contours.png");
//Prepare the image for findContours
cv::cvtColor(image, image, CV_BGR2GRAY);
cv::threshold(image, image, 128, 255, CV_THRESH_BINARY);
//Find the contours. Use the contourOutput Mat so the original image doesn't get overwritten
std::vector<std::vector<cv::Point> > contours;
cv::Mat contourOutput = image.clone();
cv::findContours(contourOutput, contours, CV_RETR_LIST, CV_CHAIN_APPROX_NONE);
////convexityDefects
vector<vector<Point> >hull(contours.size());
vector<vector<int> > hullsI(contours.size()); // Indices to contour points
vector<vector<Vec4i>> defects(contours.size());
for (int i = 0; i < contours.size(); i++)
{
convexHull(contours[i], hull[i], false);
convexHull(contours[i], hullsI[i], false);
if (hullsI[i].size() > 3) // You need more than 3 indices
{
convexityDefects(contours[i], hullsI[i], defects[i]);
}
}
///// Draw convexityDefects
for (int i = 0; i < contours.size(); ++i)
{
for (const Vec4i& v : defects[i])
{
float depth = v[3]/256;
if (depth >= 0) // filter defects by depth, e.g more than 10
{
int startidx = v[0]; Point ptStart(contours[i][startidx]);
int endidx = v[1]; Point ptEnd(contours[i][endidx]);
int faridx = v[2]; Point ptFar(contours[i][faridx]);
circle(image, ptFar, 4, Scalar(255, 255, 255), 2);
cout << ptFar << endl;
}
}
}
//
cv::imshow("Input Image", image);
cvMoveWindow("Input Image", 0, 0);
//
waitKey(0);
}
Can someone make the code and find the red dot? please help.
now i want find "convexity defects" from inside,not outside like this image:
Someone can help me??
It is very important to use
convexHull(contours[i], hullsI[i], true);
That is, with the last argument "true" for indices. I'm almost certain this is the reason it cannot find all the defects. Before fixing this, it is not much sense try to find other bugs (if any).
I am trying to process a JPEG Binary data in OpenCV. When I do that I get Segmentation fault (core dumped).
I read JPEG file through fread command and stored in a buffer.
After reading, I copied the buffer data to a Mat variable,
When I tried to do grayscale conversion on copied data using cvtColor OpenCV function. I get Segmentation Fault.
int main( int argc, char** argv )
{
Mat threshold_output;
Mat gray_image;
unsigned char *pre_image;
FILE *read_image;
FILE *write_image;
int filesize;
size_t data, write;
read_image = fopen(argv[1] , "rb"); //Read Jpeg as Binary
write_image = fopen("output11.jpg", "wb"); //Write JPEG
if(read_image == NULL)
{
printf("Image Not Found\r\n");
}
fseek(read_image, 0, SEEK_END);
int fileLen = ftell(read_image);
fseek(read_image, 0, SEEK_SET);
pre_image = (unsigned char *)malloc(fileLen);
data = fread(pre_image, 1, fileLen, read_image);
write = fwrite(pre_image, 1, fileLen, write_image);
// Printed and verify the values
printf("File Size %d\r\n", fileLen);
printf("Read bytes %zu\r\n", data);
printf("Write bytes %zu\r\n", data);
fclose(read_image);
fclose(write_image);
/* Copy the Jpeg Binary buffer to a MAt Variable*/
cv::Mat image(Size(640, 480), CV_8UC3, pre_image); //Seg Fault comes here
/* Convert Grayscale */
cvtColor( image, gray_image, CV_BGR2GRAY);
/* Threshold conversion */
threshold( gray_image, threshold_output, 80, 255, THRESH_BINARY );
namedWindow( "Thresholded", CV_WINDOW_AUTOSIZE );
imshow( "Thresholded", image );
waitKey(0);
return 0;
}
I have attached the code for reference. I have verified that both fread and fwrite works properly.
But when I do the cvtColor only I got error.
As #Micka already pointed out, you should use cv::imdecode
You can use it with your FILE*. You probably may want to use fstreams if you're using C++. You can also rely directly on OpenCV capabilities to read files.
The code below will show you these options for reading files. Code for writing is similar (I can add it if you need it).
Remember that if you want to write the binary stream, you should use imencode
#include <opencv2\opencv.hpp>
#include <fstream>
#include <stdio.h>
using namespace std;
using namespace cv;
int main()
{
////////////////////////////////
// Method 1: using FILE*
////////////////////////////////
FILE* read_image = fopen("path_to_image", "rb");
if (read_image == NULL)
{
printf("Image Not Found\n");
}
fseek(read_image, 0, SEEK_END);
int fileLen = ftell(read_image);
fseek(read_image, 0, SEEK_SET);
unsigned char* pre_image = (unsigned char *)malloc(fileLen);
size_t data = fread(pre_image, 1, fileLen, read_image);
// Printed and verify the values
printf("File Size %d\n", fileLen);
printf("Read bytes %d\n", data);
fclose(read_image);
vector<unsigned char> buffer(pre_image, pre_image + data);
Mat img = imdecode(buffer, IMREAD_ANYCOLOR);
////////////////////////////////
//// Method 2: using fstreams
////////////////////////////////
//ifstream ifs("path_to_image", iostream::binary);
//filebuf* pbuf = ifs.rdbuf();
//size_t size = pbuf->pubseekoff(0, ifs.end, ifs.in);
//pbuf->pubseekpos(0, ifs.in);
//vector<char> buffer(size);
//pbuf->sgetn(buffer.data(), size);
//ifs.close();
//Mat img = imdecode(buffer, IMREAD_ANYCOLOR);
////////////////////////////////
//// Method 3: using imread
////////////////////////////////
//Mat img = imread("path_to_image", IMREAD_ANYCOLOR);
// Work with img as you want
imshow("img", img);
waitKey();
return 0;
}
OpenCV uses channels like BGR etc and can't perform computer vision operations on ENCODED images, since encoded images don't consist of pixel data but some encoded data which can be transformed to pixels. OpenCV assumes that images are already decoded so it can work on pixel data.
BUT: you can use a binary image buffer (like your pre_image) and let openCV DECODE it.
use cv::imdecode to do it and after that you'll get a legal cv::Mat image. http://docs.opencv.org/modules/highgui/doc/reading_and_writing_images_and_video.html#imdecode
i've got the code below:
// Image Processing.cpp : Defines the entry point for the console application.
//
//Save an available image.
#include "stdafx.h"
#include "cv.h"
#include "highgui.h"
#include "cxcore.h"
/*
The purpose of this program is to show an example of THRESHOLDING.
*/
int _tmain(int argc, _TCHAR* argv[])
{
IplImage* src = cvLoadImage("D:\\document\\Study\\university of technology\\semester_8\\Computer Vision\\Pics for test\\black-white 4.jpg");
IplImage* dst = cvCreateImage(cvGetSize(src),IPL_DEPTH_8U,3);
IplImage* temp1 = cvCreateImage(cvGetSize(src),IPL_DEPTH_8U,1);
IplImage* temp2 = cvCreateImage(cvGetSize(src),IPL_DEPTH_8U,1);
cvCvtColor(src,temp1,CV_RGB2GRAY);
cvSobel(temp1,temp2,0,1,3);
cvMerge(temp2,temp2,temp2,NULL,dst);
cvNamedWindow("src",1);
cvNamedWindow("dst",1);
cvShowImage("src",src);
cvShowImage("dst",temp2);
cvWaitKey(0);
cvReleaseImage(&src);
//cvReleaseImage(&dst);
cvDestroyAllWindows();
return 0;
}
when i run it, there's an warning as the picture below:
but if i still click on "countinue" button, the result is displayed!
hope someone can give me an explaination !
The result is correct. The description of the program is not. Your xorder=0 and yorder=1 which means that you are detecting the first derivative in the y-direction. The white pixels in the image correspond to boundaries that can be detected by a vertical derivative, namely as close to horizontal boundaries as possible. This is why the vertical lines are barely ever detected.
CvSobel by itself has NOTHING to do with thresholding. CvSobel is a function used for finding boundaries and contours. Thresholding is most commonly an operation that creates a black-and-white image from a greyscale image. It is also called image binarization.
If you want to threshold an image, start with cvThreshold and cvAdaptiveThreshold.
i've fixed it, here is my code:
// Image Processing.cpp : Defines the entry point for the console application.
//
//Save an available image.
#include "stdafx.h"
#include "cv.h"
#include "highgui.h"
#include "cxcore.h"
/*
The purpose of this program is to show an example of Sobel method.
*/
int _tmain(int argc, _TCHAR* argv[])
{
IplImage* src = cvLoadImage("D:\\document\\Study\\university of technology\\semester_8\\Computer Vision\\Pics for test\\black-white 4.jpg");
IplImage* dst = cvCreateImage(cvGetSize(src),IPL_DEPTH_8U,1);
IplImage* dst_x = cvCreateImage(cvGetSize(src),IPL_DEPTH_8U,1);
IplImage* dst_y = cvCreateImage(cvGetSize(src),IPL_DEPTH_8U,1);
IplImage* temp1 = cvCreateImage(cvGetSize(src),IPL_DEPTH_8U,1);
IplImage* temp2 = cvCreateImage(cvGetSize(src),IPL_DEPTH_16S,1);
cvCvtColor(src,temp1,CV_RGB2GRAY);
cvSobel(temp1,temp2,0,1,3);
cvConvertScale(temp2,dst_y,1.0,0);
cvSobel(temp1,temp2,1,0,3);
cvConvertScale(temp2,dst_x,1.0,0);
//k nen dao ham cung luc theo x va y ma nen dao ham rieng roi dung ham cvAdd.
//cvSobel(temp1,temp2,1,1,3);
//cvConvertScale(temp2,dst,1.0,0);
cvAdd(dst_x,dst_y,dst,NULL);
cvNamedWindow("src",1);
cvNamedWindow("dst",1);
cvNamedWindow("dst_x",1);
cvNamedWindow("dst_y",1);
cvShowImage("src",src);
cvShowImage("dst",dst);
cvShowImage("dst_x",dst_x);
cvShowImage("dst_y",dst_y);
cvWaitKey(0);
cvReleaseImage(&src);
cvReleaseImage(&dst);
cvReleaseImage(&temp1);
cvReleaseImage(&temp2);
cvDestroyAllWindows();
return 0;
}
I'm trying to build the following sample code:
#include "cv.h"
#include "highgui.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <math.h>
#include <float.h>
#include <limits.h>
#include <time.h>
#include <ctype.h>
// Create a string that contains the exact cascade name
const char* cascade_name = "/usr/share/src/OpenCV-2.3.1/data/haarcascades/haarcascade_frontalface_alt.xml";
// "C:/Program Files/OpenCV/data/haarcascades/haarcascade_frontalface_alt.xml";
/* "haarcascade_profileface.xml";*/
// Function prototype for detecting and drawing an object from an image
void detect_and_draw( IplImage* image );
// Main function, defines the entry point for the program.
int main( int argc, char** argv )
{
// Create a sample image
IplImage *img = cvLoadImage("1.pgm");
// Call the function to detect and draw the face positions
detect_and_draw(img);
// Wait for user input before quitting the program
cvWaitKey();
// Release the image
cvReleaseImage(&img);
// Destroy the window previously created with filename: "result"
cvDestroyWindow("result");
// return 0 to indicate successfull execution of the program
return 0;
}
// Function to detect and draw any faces that is present in an image
void detect_and_draw( IplImage* img )
{
// Create memory for calculations
static CvMemStorage* storage = 0;
// Create a new Haar classifier
static CvHaarClassifierCascade* cascade = 0;
int scale = 1;
// Create a new image based on the input image
IplImage* temp = cvCreateImage( cvSize(img->width/scale,img->height/scale), 8, 3 );
// Create two points to represent the face locations
CvPoint pt1, pt2;
int i;
// Load the HaarClassifierCascade
cascade = (CvHaarClassifierCascade*)cvLoad( cascade_name, 0, 0, 0 );
// Check whether the cascade has loaded successfully. Else report and error and quit
if( !cascade )
{
fprintf( stderr, "ERROR: Could not load classifier cascade\n" );
return;
}
// Allocate the memory storage
storage = cvCreateMemStorage(0);
// Create a new named window with title: result
cvNamedWindow( "result", 1 );
// Clear the memory storage which was used before
cvClearMemStorage( storage );
// Find whether the cascade is loaded, to find the faces. If yes, then:
if( cascade )
{
// There can be more than one face in an image. So create a growable sequence of faces.
// Detect the objects and store them in the sequence
CvSeq* faces = cvHaarDetectObjects( img, cascade, storage,
1.1, 2, CV_HAAR_DO_CANNY_PRUNING,
cvSize(40, 40) );
// Loop the number of faces found.
for( i = 0; i < (faces ? faces->total : 0); i++ )
{
// Create a new rectangle for drawing the face
CvRect* r = (CvRect*)cvGetSeqElem( faces, i );
// Find the dimensions of the face,and scale it if necessary
pt1.x = r->x*scale;
pt2.x = (r->x+r->width)*scale;
pt1.y = r->y*scale;
pt2.y = (r->y+r->height)*scale;
// Draw the rectangle in the input image
cvRectangle( img, pt1, pt2, CV_RGB(255,0,0), 3, 8, 0 );
}
}
// Show the image in the window named "result"
cvShowImage( "result", img );
// Release the temp image created.
cvReleaseImage( &temp );
}
And the path /usr/share/src....is the right path where the xml file is. I've linked the opencv libraries: opencv_core, opencv_imgproc, opencv_highgui and opencv_video to eclipse (and I think they are correctly linked since I build other opencv projects in this way). But Eclipse keeps throwing the following errors:
Invoking: MacOS X C++ Linker
g++ -L/usr/local/include/opencv -L/usr/local/include/opencv2 -L/usr/local/lib -o "OpenCVFace" ./main.o -lopencv_core -lopencv_highgui -lopencv_video -lopencv_imgproc
Undefined symbols for architecture x86_64:
"_cvHaarDetectObjects", referenced from:
detect_and_draw(_IplImage*) in main.o
ld: symbol(s) not found for architecture x86_64
collect2: ld returned 1 exit status
make: *** [OpenCVFace] Error 1
**** Build Finished ****
I can see the cvHaarDetectObjects function is highlighted in Eclipse (which turned to purple color). Any ideas of how to solve the problem? Thanks!
You need to link to opencv_objdetect; include -lopencv_objdetect in the link flags.
Is there a way to easily extract the DCT coefficients (and quantization parameters) from encoded images and video? Any decoder software must be using them to decode block-DCT encoded images and video. So I'm pretty sure the decoder knows what they are. Is there a way to expose them to whomever is using the decoder?
I'm implementing some video quality assessment algorithms that work directly in the DCT domain. Currently, the majority of my code uses OpenCV, so it would be great if anyone knows of a solution using that framework. I don't mind using other libraries (perhaps libjpeg, but that seems to be for still images only), but my primary concern is to do as little format-specific work as possible (I don't want to reinvent the wheel and write my own decoders). I want to be able to open any video/image (H.264, MPEG, JPEG, etc) that OpenCV can open, and if it's block DCT-encoded, to get the DCT coefficients.
In the worst case, I know that I can write up my own block DCT code, run the decompressed frames/images through it and then I'd be back in the DCT domain. That's hardly an elegant solution, and I hope I can do better.
Presently, I use the fairly common OpenCV boilerplate to open images:
IplImage *image = cvLoadImage(filename);
// Run quality assessment metric
The code I'm using for video is equally trivial:
CvCapture *capture = cvCaptureFromAVI(filename);
while (cvGrabFrame(capture))
{
IplImage *frame = cvRetrieveFrame(capture);
// Run quality assessment metric on frame
}
cvReleaseCapture(&capture);
In both cases, I get a 3-channel IplImage in BGR format. Is there any way I can get the DCT coefficients as well?
Well, I did a bit of reading and my original question seems to be an instance of wishful thinking.
Basically, it's not possible to get the DCT coefficients from H.264 video frames for the simple reason that H.264 doesn't use DCT. It uses a different transform (integer transform). Next, the coefficients for that transform don't necessarily change on a frame-by-frame basis -- H.264 is smarter cause it splits up frames into slices. It should be possible to get those coefficients through a special decoder, but I doubt OpenCV exposes it for the user.
For JPEG, things are a bit more positive. As I suspected, libjpeg exposes the DCT coefficients for you. I wrote a small app to show that it works (source at the end). It makes a new image using the DC term from each block. Because the DC term is equal to the block average (after proper scaling), the DC images are downsampled versions of the input JPEG image.
EDIT: fixed scaling in source
Original image (512 x 512):
DC images (64x64): luma Cr Cb RGB
Source (C++):
#include <stdio.h>
#include <assert.h>
#include <cv.h>
#include <highgui.h>
extern "C"
{
#include "jpeglib.h"
#include <setjmp.h>
}
#define DEBUG 0
#define OUTPUT_IMAGES 1
/*
* Extract the DC terms from the specified component.
*/
IplImage *
extract_dc(j_decompress_ptr cinfo, jvirt_barray_ptr *coeffs, int ci)
{
jpeg_component_info *ci_ptr = &cinfo->comp_info[ci];
CvSize size = cvSize(ci_ptr->width_in_blocks, ci_ptr->height_in_blocks);
IplImage *dc = cvCreateImage(size, IPL_DEPTH_8U, 1);
assert(dc != NULL);
JQUANT_TBL *tbl = ci_ptr->quant_table;
UINT16 dc_quant = tbl->quantval[0];
#if DEBUG
printf("DCT method: %x\n", cinfo->dct_method);
printf
(
"component: %d (%d x %d blocks) sampling: (%d x %d)\n",
ci,
ci_ptr->width_in_blocks,
ci_ptr->height_in_blocks,
ci_ptr->h_samp_factor,
ci_ptr->v_samp_factor
);
printf("quantization table: %d\n", ci);
for (int i = 0; i < DCTSIZE2; ++i)
{
printf("% 4d ", (int)(tbl->quantval[i]));
if ((i + 1) % 8 == 0)
printf("\n");
}
printf("raw DC coefficients:\n");
#endif
JBLOCKARRAY buf =
(cinfo->mem->access_virt_barray)
(
(j_common_ptr)cinfo,
coeffs[ci],
0,
ci_ptr->v_samp_factor,
FALSE
);
for (int sf = 0; (JDIMENSION)sf < ci_ptr->height_in_blocks; ++sf)
{
for (JDIMENSION b = 0; b < ci_ptr->width_in_blocks; ++b)
{
int intensity = 0;
intensity = buf[sf][b][0]*dc_quant/DCTSIZE + 128;
intensity = MAX(0, intensity);
intensity = MIN(255, intensity);
cvSet2D(dc, sf, (int)b, cvScalar(intensity));
#if DEBUG
printf("% 2d ", buf[sf][b][0]);
#endif
}
#if DEBUG
printf("\n");
#endif
}
return dc;
}
IplImage *upscale_chroma(IplImage *quarter, CvSize full_size)
{
IplImage *full = cvCreateImage(full_size, IPL_DEPTH_8U, 1);
cvResize(quarter, full, CV_INTER_NN);
return full;
}
GLOBAL(int)
read_JPEG_file (char * filename, IplImage **dc)
{
/* This struct contains the JPEG decompression parameters and pointers to
* working space (which is allocated as needed by the JPEG library).
*/
struct jpeg_decompress_struct cinfo;
struct jpeg_error_mgr jerr;
/* More stuff */
FILE * infile; /* source file */
/* In this example we want to open the input file before doing anything else,
* so that the setjmp() error recovery below can assume the file is open.
* VERY IMPORTANT: use "b" option to fopen() if you are on a machine that
* requires it in order to read binary files.
*/
if ((infile = fopen(filename, "rb")) == NULL) {
fprintf(stderr, "can't open %s\n", filename);
return 0;
}
/* Step 1: allocate and initialize JPEG decompression object */
cinfo.err = jpeg_std_error(&jerr);
/* Now we can initialize the JPEG decompression object. */
jpeg_create_decompress(&cinfo);
/* Step 2: specify data source (eg, a file) */
jpeg_stdio_src(&cinfo, infile);
/* Step 3: read file parameters with jpeg_read_header() */
(void) jpeg_read_header(&cinfo, TRUE);
/* We can ignore the return value from jpeg_read_header since
* (a) suspension is not possible with the stdio data source, and
* (b) we passed TRUE to reject a tables-only JPEG file as an error.
* See libjpeg.txt for more info.
*/
/* Step 4: set parameters for decompression */
/* In this example, we don't need to change any of the defaults set by
* jpeg_read_header(), so we do nothing here.
*/
jvirt_barray_ptr *coeffs = jpeg_read_coefficients(&cinfo);
IplImage *y = extract_dc(&cinfo, coeffs, 0);
IplImage *cb_q = extract_dc(&cinfo, coeffs, 1);
IplImage *cr_q = extract_dc(&cinfo, coeffs, 2);
IplImage *cb = upscale_chroma(cb_q, cvGetSize(y));
IplImage *cr = upscale_chroma(cr_q, cvGetSize(y));
cvReleaseImage(&cb_q);
cvReleaseImage(&cr_q);
#if OUTPUT_IMAGES
cvSaveImage("y.png", y);
cvSaveImage("cb.png", cb);
cvSaveImage("cr.png", cr);
#endif
*dc = cvCreateImage(cvGetSize(y), IPL_DEPTH_8U, 3);
assert(dc != NULL);
cvMerge(y, cr, cb, NULL, *dc);
cvReleaseImage(&y);
cvReleaseImage(&cb);
cvReleaseImage(&cr);
/* Step 7: Finish decompression */
(void) jpeg_finish_decompress(&cinfo);
/* We can ignore the return value since suspension is not possible
* with the stdio data source.
*/
/* Step 8: Release JPEG decompression object */
/* This is an important step since it will release a good deal of memory. */
jpeg_destroy_decompress(&cinfo);
fclose(infile);
return 1;
}
int
main(int argc, char **argv)
{
int ret = 0;
if (argc != 2)
{
fprintf(stderr, "usage: %s filename.jpg\n", argv[0]);
return 1;
}
IplImage *dc = NULL;
ret = read_JPEG_file(argv[1], &dc);
assert(dc != NULL);
IplImage *rgb = cvCreateImage(cvGetSize(dc), IPL_DEPTH_8U, 3);
cvCvtColor(dc, rgb, CV_YCrCb2RGB);
#if OUTPUT_IMAGES
cvSaveImage("rgb.png", rgb);
#else
cvNamedWindow("DC", CV_WINDOW_AUTOSIZE);
cvShowImage("DC", rgb);
cvWaitKey(0);
#endif
cvReleaseImage(&dc);
cvReleaseImage(&rgb);
return 0;
}
You can use, libjpeg to extract dct data of your jpeg file, but for h.264 video file, I can't find any open source code that give you dct data (actully Integer dct data). But you can use h.264 open source software like JM, JSVM or x264. In these two source file, you have to find their specific function that make use of dct function, and change it to your desire form, to get your output dct data.
For Image:
use the following code, and after read_jpeg_file( infilename, v, quant_tbl ), v and quant_tbl will have dct data and quantization table of your jpeg image respectively.
I used Qvector to store my output data, change it to your preferred c++ array list.
#include <iostream>
#include <stdio.h>
#include <jpeglib.h>
#include <stdlib.h>
#include <setjmp.h>
#include <fstream>
#include <QVector>
int read_jpeg_file( char *filename, QVector<QVector<int> > &dct_coeff, QVector<unsigned short> &quant_tbl)
{
struct jpeg_decompress_struct cinfo;
struct jpeg_error_mgr jerr;
FILE * infile;
if ((infile = fopen(filename, "rb")) == NULL) {
fprintf(stderr, "can't open %s\n", filename);
return 0;
}
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_decompress(&cinfo);
jpeg_stdio_src(&cinfo, infile);
(void) jpeg_read_header(&cinfo, TRUE);
jvirt_barray_ptr *coeffs_array = jpeg_read_coefficients(&cinfo);
for (int ci = 0; ci < 1; ci++)
{
JBLOCKARRAY buffer_one;
JCOEFPTR blockptr_one;
jpeg_component_info* compptr_one;
compptr_one = cinfo.comp_info + ci;
for (int by = 0; by < compptr_one->height_in_blocks; by++)
{
buffer_one = (cinfo.mem->access_virt_barray)((j_common_ptr)&cinfo, coeffs_array[ci], by, (JDIMENSION)1, FALSE);
for (int bx = 0; bx < compptr_one->width_in_blocks; bx++)
{
blockptr_one = buffer_one[0][bx];
QVector<int> tmp;
for (int bi = 0; bi < 64; bi++)
{
tmp.append(blockptr_one[bi]);
}
dct_coeff.push_back(tmp);
}
}
}
// coantization table
j_decompress_ptr dec_cinfo = (j_decompress_ptr) &cinfo;
jpeg_component_info *ci_ptr = &dec_cinfo->comp_info[0];
JQUANT_TBL *tbl = ci_ptr->quant_table;
for(int ci =0 ; ci < 64; ci++){
quant_tbl.append(tbl->quantval[ci]);
}
return 1;
}
int main()
{
QVector<QVector<int> > v;
QVector<unsigned short> quant_tbl;
char *infilename = "your_image.jpg";
std::ofstream out;
out.open("out_dct.txt");
if( read_jpeg_file( infilename, v, quant_tbl ) > 0 ){
for(int j = 0; j < v.size(); j++ ){
for (int i = 0; i < v[0].size(); ++i){
out << v[j][i] << "\t";
}
out << "---------------" << std::endl;
}
out << "\n\n\n" << std::string(10,'-') << std::endl;
out << "\nQauntization Table:" << std::endl;
for(int i = 0; i < quant_tbl.size(); i++ ){
out << quant_tbl[i] << "\t";
}
}
else{
std::cout << "Can not read, Returned With Error";
return -1;
}
out.close();
return 0;
}