I want to learn image processing in C++, but I don't want to use any 3rd party library for image manipulation. Use of library for displaying the image(s) is okay, but all manipulations are to be done manually.
Please point me to some good tutorials. I'm a beginner in this field, so I also need to know how to display an image.
Seems you lack basic knowledge of Digital Image Processing, I recommand to you this book.
Digital Image Processing (3rd Edition) Rafael C.Gonzalez / Richard E.Woods http://www.amazon.com/dp/013168728X
For basic operation using OpenCV(which I am familiar with), here is an example:
/*
function:image reverse
*/
#include "stdafx.h"
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <cv.h>
#include <highgui.h>
int main(int argc, char *argv[])
{
IplImage* img = 0;
int height,width,step,channels;
uchar *data;
int i,j,k;
if(argc<2)
{
printf("Usage: main <image-file-name>/n/7");
exit(0);
}
// Load image
img=cvLoadImage(argv[1],-1);
if(!img)
{
printf("Could not load image file: %s\n",argv[1]);
exit(0);
}
// acquire image info
height = img->height;
width = img->width;
step = img->widthStep;
channels = img->nChannels;
data = (uchar *)img->imageData;
printf("Processing a %dx%d image with %d channels/n",height,width,channels);
// create display window
cvNamedWindow("mainWin", CV_WINDOW_AUTOSIZE);
cvMoveWindow("mainWin", 100, 100);
// reverse image
for(i=0;i<height;i++)
for(j=0;j<width;j++)
for(k=0;k<channels;k++)
data[i*step+j*channels+k]=255-data[i*step+j*channels+k];
// display reversed image
cvShowImage("mainWin", img );
cvWaitKey(0);
cvReleaseImage(&img );
printf("height=%d width=%d step=%d channels=%d",height,width,step,channels);
return 0;
}
Try CImg (it's entirely self-contained) - http://cimg.sourceforge.net/
Related
I have a single channel of 64-bit floats image that I am trying to transform into an unsigned char using OpenCV. I can successfully visualize the image and resize it as it is too big. However when I am trying to transform the resized image into an unsigned char I don't see anything.
I am doing the transformation using the following function as advised here.
I initially tried const uchar* inBuffer = desc.data; to transform it but according to the same source it seems to be unsafe and therefore opted for a recasting method. That also didn't work but that it seemed at my best understanding the best choice. The code is below:
#include <opencv2/core.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/opencv.hpp>
#include <iostream>
#include <string>
using namespace cv;
using namespace std;
int main(int argc, char** argv)
{
String imageName( "/home/to/Desktop/Myexample.tif" );
if( argc > 1)
{
imageName = argv[1];
}
Mat image;
Mat outImage;
Mat corrected;
// Read the file
image = cv::imread( imageName, IMREAD_UNCHANGED );
// Check for invalid input
if(image.empty())
{
cout << "Could not open or find the image" << std::endl ;
return -1;
}
cv::resize(image, outImage, Size(800,800));
cv::namedWindow("Resized", WINDOW_AUTOSIZE);
cv::imshow("Resized", outImage+220);
// Transformation of the resized image into a unsigned char for better visualization
cv::resize(outImage, corrected, Size(800,800));
cv::namedWindow("Corrected", WINDOW_AUTOSIZE);
// From here nothing is showing up
unsigned char const* inBuffer = reinterpret_cast<unsigned char const*>(outImage.data);
cv::imshow("Corrected", *inBuffer);
cv::waitKey(0);
return 0;
}
Another thing I thought could have been useful is from the following source where it was advised to use a double conversion. I understand that it is fast in terms of computation but at the same time this didn't give me any useful result.
Thank you in advance for shedding light on this matter.
I am a beginner in OpenCV and Qt, my project now is combining multiple images and display it on Qt Creator.
#include <stdio.h>
#include <iostream>
#include <mutex>
#include <opencv2/opencv.hpp>
using namespace std;
int main(int argc, char** argv) {
string img_path = "/home/m/pictures/cat.jpg";
std::vector<cv::Mat> img_pool;
for (int i=0;i<10;i++)
{
cv::Mat data = cv::imread(img_path,-1);
img_pool.push_back(data);
}
cv::Mat data = cv::imread(img_path,-1);
cv::namedWindow("image", CV_WINDOW_NORMAL);
cv::imshow("image",data);
cv::waitKey(0);
cv::Mat data_dst = cv::Mat::zeros(500, 500, data.type());
cv::Mat data_resize;
for(int i=0;i<10;i++)
{
for(int j=0;j<10;j++)
{
cv::resize( img_pool[3], data_resize, cv::Size(50,50));
cv::Rect f_target(i*50,j*50,50,50);
data_resize.copyTo(data_dst(f_target));
}
}
cv::namedWindow("image_n", CV_WINDOW_NORMAL);
cv::imshow("image_n",data_dst);
cv::waitKey(0);
return 0;
}
Here is the result:
My code now can display one image but what I want to do is display different multiple images, I think I need to load the images or image path to the vector but I failed, so someone can help me?
There is no Qt used in your code. If you want something like this with Qt, you can use a simple widget with a grid layout or a flowlayout. Then load all the images from a path in an array of QImage and the display it.
You can find an example with FlowLayout here. You can use a QLabel to display the image, convert your QImage to QPixmap and the use:
QImage yourImage("path");
QLabel image new QLabel(centralwidget);
imagelabel->setGeometry(QRect(20, 10, 371, 311));
imagelabel->setPixmap(QPixmap(QPixmap::fromImage(yourImage));
If you are new with Qt, you can integrate it easily with QML using a FlowLayout and and array of QML components. Look this example of the usage of an ImageViewer
I am trying to write a very basic video capturing program using opencv, but despite all my efforts, nothing gets written. I am fairly sure that i am following all the tutorials one can find on the subject.
Here is the code i am using:
#include <opencv2\core\core.hpp>
#include <opencv2\imgproc\imgproc.hpp>
#include <opencv2\highgui\highgui.hpp>
#include <videoInput.h>
static const cv::Size _SIZE(640, 480);
static const int FPS = 20;
int webcam = 0;
std::auto_ptr<videoInput> VI(NULL);
std::auto_ptr<cv::VideoWriter> outputVideo(NULL);
cv::Mat frame(_SIZE.height, _SIZE.width, CV_8UC3);
// get device list create videoInput
videoInput::listDevices();
VI.reset(new videoInput())
// choose first device
VI->setupDevice(webcam, _SIZE.width, _SIZE.height);
// always check
if(!VI->isDeviceSetup(webcam))
return -1; //-->
// set device frame rate
VI->setIdealFramerate(webcam, FPS);
// create named window and image
cv::namedWindow("CAM");
do
if (VI->isFrameNew(webcam))
{
VI->getPixels(webcam, (unsigned char*)frame.data, false, true); // получение пикселей в BGR
if (outputVideo.get())
{
(*outputVideo).write( frame);
}
char c = cv::waitKey(5);
if (!IsWindowVisible((HWND)cvGetWindowHandle("CAM")) || c==27)
{
exit(0);
}
cv::imshow("CAM", frame);
} while(1);
I have tried various extension and various Fourcc values. Usually, on any extension except avi, writer is created but does nothing. on the contrary, avi files writers simply fail to be created.
I have read that probably codecs are missing, but what does that mean - what exactly do i need to put where for them to be found by opencv?
All in all, i am very confused. This is tutorial code, it should work.
I'm trying to extract images from gif using giflib in order to bind them in Opencv Mat.
I'm currently using Opencv-2.4.5 and giflib-4.1.6-10.
My problem is that I can extract only extract the first image of the gif.
The second and the others are scratched, I think it is a matter of bits alignement.
Following the doc: http://giflib.sourceforge.net/gif_lib.html
SavedImage *SavedImages; /* Image sequence (high-level API) */
Should provide a pointer to bits of images.
#include <gif_lib.h>
#include <iostream>
#include <assert.h>
#include <string.h>
#include <stdlib.h>
#include "opencv2/opencv.hpp"
using namespace std;
using namespace cv;
int main(int ac, char **av){
int *err;
GifFileType *f = DGifOpenFileName(av[1]);
assert(f != NULL);
int ret = DGifSlurp(f);
assert(ret == GIF_OK);
int width = f->SWidth;
int height = f->SHeight;
cout << f->ImageCount << endl;
cout << width << " : " << height<< endl;
cout << f->SColorResolution << endl;
// SavedImage *image = &f->SavedImages[0]; Does actually works
SavedImage *image = &f->SavedImages[1]; // that compile but the result is a scratched img
Mat img = Mat(Size(width, height), CV_8UC1, image->RasterBits);
imwrite("test.png", img);
DGifCloseFile(f);
return 0;
}
I don't want to use ImageMagick to keep a little piece of code and keep it "light".
Thanks for your Help.
Did you check whether your GIF file is interlaced ? If it is , you should consider it before storing rasterbits into a bitmap format.
Also check the top,left,width and height of the "SavedImages" , every frame does not need to cover all canvas so you should only overwrite pixels that are different from the last frame.
So I'm trying to use the webp API to encode images. Right now I'm going to be using openCV to open and manipulate the images, then I want to save them off as webp. Here's the source I'm using:
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <cv.h>
#include <highgui.h>
#include <webp/encode.h>
int main(int argc, char *argv[])
{
IplImage* img = 0;
int height,width,step,channels;
uchar *data;
int i,j,k;
if (argc<2) {
printf("Usage:main <image-file-name>\n\7");
exit(0);
}
// load an image
img=cvLoadImage(argv[1]);
if(!img){
printf("could not load image file: %s\n",argv[1]);
exit(0);
}
// get the image data
height = img->height;
width = img->width;
step = img->widthStep;
channels = img->nChannels;
data = (uchar *)img->imageData;
printf("processing a %dx%d image with %d channels \n", width, height, channels);
// create a window
cvNamedWindow("mainWin", CV_WINDOW_AUTOSIZE);
cvMoveWindow("mainWin",100,100);
// invert the image
for (i=0;i<height;i++) {
for (j=0;j<width;j++) {
for (k=0;k<channels;k++) {
data[i*step+j*channels+k] = 255-data[i*step+j*channels+k];
}
}
}
// show the image
cvShowImage("mainWin", img);
// wait for a key
cvWaitKey(0);
// release the image
cvReleaseImage(&img);
float qualityFactor = .9;
uint8_t** output;
FILE *opFile;
size_t datasize;
printf("encoding image\n");
datasize = WebPEncodeRGB((uint8_t*)data,width,height,step,qualityFactor,output);
printf("writing file out\n");
opFile=fopen("output.webp","w");
fwrite(output,1,(int)datasize,opFile);
}
When I execute this, I get this:
nato#ubuntu:~/webp/webp_test$ ./helloWorld ~/Pictures/mars_sunrise.jpg
processing a 2486x1914 image with 3 channels
encoding image
Segmentation fault
It displays the image just fine, but segfaults on the encoding. My initial guess was that it's because I'm releasing the img before I try to write out the data, but it doesn't seem to matter whether I release it before or after I try the encoding. Is there something else I'm missing that might cause this problem? Do I have to make a copy of the image data or something?
The WebP api docs are... sparse. Here's what the README says about WebPEncodeRGB:
The main encoding functions are available in the header src/webp/encode.h
The ready-to-use ones are:
size_t WebPEncodeRGB(const uint8_t* rgb, int width, int height,
int stride, float quality_factor, uint8_t** output);
The docs specifically do not say what the 'stride' is, but I'm assuming that it's the same as the 'step' from opencv. Is that reasonable?
Thanks in advance!
First, don't release the image if you use it later. Second, your output argument is pointing to non-initialized address. This is how to use initialized memory for the output address:
uint8_t* output;
datasize = WebPEncodeRGB((uint8_t*)data, width, height, step, qualityFactor, &output);
You release the image with cvReleaseImage before you try to use the pointer to the image data for the encoding. Probably that release function frees the image buffer and your data pointer now doesn't point to valid memory anymore.
This might be the reason for your segfault.
so it looks like the problem was here:
// load an image
img=cvLoadImage(argv[1]);
The function cvLoadImage takes an extra parameter
cvLoadImage(const char* filename, int iscolor=CV_LOAD_IMAGE_COLOR)
and when I changed to
img=cvLoadImage(argv[1],1);
the segfault went away.