How to work with SDL_surface pixel data? - c

I need to read bmp image file, increase the brightness, and then save the bmp. I decided to use SDL2, because it seemed to the easiest for me to load bmp-s. I wrote a code, but I do not understand how to work with SDL_surface pixels. It is just a pointer to the actual pixel data. How can I increase values, and then save the modified bmp? Here is my try:
SDL_Init(SDL_INIT_EVERYTHING);
SDL_Surface* picture = NULL;
Uint8 red, green, blue;
picture = SDL_LoadBMP("avxsample.bmp");
if (picture != NULL)
{
printf("BMP File is loaded!\n");
// This part is unclear for me...
SDL_SaveBMP(picture, "avxsamlpe_new.bmp");
}
else
{
printf("Cannot load BMP File!\n");
SDL_FreeSurface(picture);
}
return 0;
Anyone can help me?

Related

OpenCV canny; output image is pure gray

I am learning opencv and reading a book and following examples. The book introduced the canny filter. However there is some problem with my output. As an input image I have given a 512x512 gray scale image but the filter output is pure gray image. Here is the image:
This is the input image.
And this is the output image.
And here is the snippets:
#include <opencv\cv.h>
#include <opencv2\highgui\highgui.hpp>
#include "Resources.h"
IplImage* doCanny(
IplImage* in,
double lowThresh,
double highThresh,
double aperture
) {
if (in->nChannels != 1)
{
return 0; // Canny only handle gray scale images.
}
IplImage* out = cvCreateImage(
CvSize(cvGetSize(in)),
IPL_DEPTH_8U,
1
);
cvCanny(in, out, lowThresh, highThresh, aperture);
return out;
}
int main(int argc, char** argv)
{
IplImage* image = cvLoadImage(IMAGE_FRUIT);
IplImage* output = doCanny(image, 200, 201, 1);
cvNamedWindow("Canny", CV_WINDOW_AUTOSIZE);
cvShowImage("Canny", output);
cvWaitKey(0);
cvReleaseImage(&output);
cvDestroyWindow("Canny");
return 0;
}
Visual Studio 2015, OpenCV version 2.4.13
I think if you step through your code, you will realize the cvCanny function never gets triggered, the returned output from doCanny is a null pointer.
OpenCV's Canny edge detection algorithm only accepts gray scale image, which is why the original code has the "if (in->nChannels != 1)" check, so you need to convert your input image into a grayscale image first.
// Convert to grayscale first
IplImage* gray_image = cvCreateImage(cvGetSize(image), IPL_DEPTH_8U, 1);
cvCvtColor(image, gray_image, CV_BGR2GRAY);
// Perform Canny
IplImage* output = doCanny(gray_image, 200, 201, 3);
Additional, I think your "aperture" parameter for cvCanny is also invalid, try to use the default value 3 (or 5, 7), and you should be able to see the result.
I would also recommend using the C++ interface instead of the deprecated C interface.

Can I run Gif with c program?

I know that I can display a .png file, So I was thought that i can display a .gif file.
I am using opencv and i will send the code for the displaying of the .png file (that is working when you change the directory to a valid one).
#include <stdio.h>
#include <opencv2\highgui\highgui_c.h>
int main(void)
{
int i;
cvNamedWindow("Display window", CV_WINDOW_AUTOSIZE); //create a window
//create an image
IplImage* image = cvLoadImage("C:\\c1.png", 1); //change to a valid directory
if (!image)//The image is empty.
{
printf("could not open image\n");
}
else
{
cvShowImage("Display window", image);
cvWaitKey(0);
system("pause");
cvReleaseImage(&image);
}
return 0;
}
unfortunately there is no direct gif support in opencv.
cv2.imread(image.gif) is not possible.But there are many other alternatives to insert a GIF
You can use moviepy module to make it happen
Link for moviepy
Here is an example:
Converting a video excerpt into a GIF
importing moviepy module
from moviepy.editor import *
Then a video file is opened and selected the part between 1’22.65 (1
minute 22.65 seconds) and 1’23.2, reduce its size (to 30% of the
original) and save it as a GIF
clip = (VideoFileClip("frozen_trailer.mp4").subclip((1,22.65),(1,23.2)).resize(0.3))
clip.write_gif("use_your_head.gif")

Inverse fill image in OpenCV

I'm new to OpenCv and have been using it for a small project.
I intend to fill a single channel image all over, except a rectangle region within the image.
I have two problems.
1) Filling a single channel image with black. (cvSet wont work on single channel)
2) Carrying out the fill all over the image except a rectangle region within the image.
Any solutions?
Here's a program that shows how to fill a single channel with black and also how to set the image to black with a mask.
#include <iostream>
#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"
int main(int argc, const char * argv[]) {
cv::Mat image;
image = cv::imread("../../lena.jpg", CV_LOAD_IMAGE_GRAYSCALE);
if (!image.data) {
std::cout << "Image file not found\n";
return 1;
}
cv::namedWindow("original");
cv::imshow("original", image);
//Define the ROI rectangle
cv::Rect ROIrect(100, 100, 200, 200);
//Create a deep copy of the image
cv::Mat fill(image.clone());
//Specify the ROI
cv::Mat fillROI = fill(ROIrect);
//Fill the ROI with black
fillROI = cv::Scalar(0);
cv::namedWindow("fill");
cv::imshow("fill", fill);
cvMoveWindow("fill", 500, 40);
//create a deep copy of the image
cv::Mat inverseFill(image.clone());
//create a single-channel mask the same size as the image filled with 1
cv::Mat inverseMask(inverseFill.size(), CV_8UC1, cv::Scalar(1));
//Specify the ROI in the mask
cv::Mat inverseMaskROI = inverseMask(ROIrect);
//Fill the mask's ROI with 0
inverseMaskROI = cv::Scalar(0);
//Set the image to 0 in places where the mask is 1
inverseFill.setTo(cv::Scalar(0), inverseMask);
cv::namedWindow("inverseFill");
cv::imshow("inverseFill", inverseFill);
cvMoveWindow("inverseFill", 1000, 40);
// wait for key
cv::waitKey(0);
return 0;
}
Nested for loops would indeed be the quickest way.
Otherwise, consider making a buffer of identical size that's cleared using cvZero (all black). Then, setROI to the region that you care about, and cvCopy into the temporary buffer.
A bit mask with cvAnd is also a nice and clean solution.

Convert image document to black and white with OpenCV

I'm new to OpenCV and image processing and I'M not sure how to solve my problem.
I have a photo of document made in iPhone and I want to convert that document to black and white. I tried to use threshold but the text was not so good (a little blurry and unreadable). I'd like to text looks same as on the original image, only black, and background will be white. What can I do?
P.S. When I made a photo of part of the document, where text is quite big, then result is ok.
I will be grateful for any help.
Here are the example image I use and the result:
My attemp, maybe a little more readable than yours:
IplImage * pRGBImg = 0;
pRGBImg = cvLoadImage(input_file.c_str(), CV_LOAD_IMAGE_UNCHANGED);
if(!pRGBImg)
{
std::cout << "ERROR: Failed to load input image" << std::endl;
return -1;
}
// Allocate the grayscale image
IplImage * pGrayImg = 0;
pGrayImg = cvCreateImage(cvSize(pRGBImg->width, pRGBImg->height), pRGBImg->depth, 1);
// Convert it to grayscale
cvCvtColor(pRGBImg, pGrayImg, CV_RGB2GRAY);
// Dilate
cvDilate(pGrayImg, pGrayImg, 0, 0.2);
cvThreshold(pGrayImg, pGrayImg, 30, 255, CV_THRESH_BINARY | CV_THRESH_OTSU);
cvSmooth(pGrayImg, pGrayImg, CV_BLUR, 2, 2);
cvSaveImage("out.png", pGrayImg);
Threshold image is used for different purposes.
If u just want to convert it to b/w image just do this. USing openCV 2.2
cv::Mat image_name = cv::imread("fileName", 0);
the second parameter 0 tells to read a color image as b/w image.
And if you want to save as a b/w image file.
code this
cv::Mat image_name = cv::imread("fileName", 0);
cv::imwrite(image_name, "bw_filename.jpg");
Using Adaptive Gaussian Thresholding is a good idea here. This will also enhance the quality of text written in the image.
You can do that by simply giving the command:
AdaptiveThreshold(src_Mat, dst_Mat, Max_value, Adaptive_Thresholding_Method, Thresholding_type, blocksize, C);

OpenCV show both incoming video and modified video in separate windows

This should be easy. I have a video stream coming in from my webcam. I'm just playing with image transformation etc. I'd like to be able to view the original images (video input) in one window and the transformed video in another. Problem is, as soon as I start capturing video instead of just single images, the original video window displays transformed video. I don't understand why.
cvNamedWindow("in", CV_WINDOW_AUTOSIZE);
cvNamedWindow("out", CV_WINDOW_AUTOSIZE);
CvCapture *fc = cvCaptureFromCAM(0);
IplImage* frame = cvQueryFrame(fc);
if (!frame) {
return 0;
}
IplImage* greyscale = cvCreateImage(cvGetSize(frame), IPL_DEPTH_8U, 1);
IplImage* output = cvCreateImage(cvGetSize(frame),IPL_DEPTH_32F , 1);
while(1){
frame= cvQueryFrame(fc);
cvShowImage("in", frame);
// manually convert to greyscale
for (int y = 0; y < frame->height; y++) {
uchar* p = (uchar*) frame->imageData + y* frame->widthStep; // pointer to row
uchar* gp = (uchar*) greyscale->imageData + y*greyscale->widthStep;
for(int x = 0; x < frame->width; x++){
gp[x] = (p[3*x] + p[3*x+1] + p[3*x+2])/3; // average RGB values
}
}
cvShowImage("out", greyscale);
char c = cvWaitKey(33);
if (c == 27) {
return 0;
}
}
In this simple example, both video streams end up appearing greyscale... The pointer values and imagedata for frame and greyscale are totally different. If I stop showing greyscale in the "out" window, then frame will appear in color.
Also, if I continue and apply a Sobel operation on the greyscale image and display the result in "out", both "in" and "out" windows will show the Sobel image!
Any ideas?
Hmm This was weird, but it seems using CV_WINDOW_AUTOSIZE was the problem? Perhaps it's not supported in OpenCV 2.1 (which I'm pretty sure is what I'm running). Anyways, using 0 instead of CV_WINDOW_AUTOSIZE when creating the windows works fine.
I have tried your code with openCV 2.0 under mandriva 2010 and it is working fine either with CV_WINDOW_AUTOSIZE or 0.
You may try to convert to grayscale with cvCvtColor(frame,grayscale,CV_RGB2GRAY) and see if the problem persist.

Resources