Opencv cvSetImageROI coordinate issue - c

in my app i used opencv to cropped an image with specific coordinate, but the problem it was when i move the coord of the left side it was the up side make change so i didn't understand.
//assignment of calculates ration between view resolution and resolution of the photograph
double scaleX = (outPutImage.frame.size.width/newCoordRect.imgWidth);
double scaleY = (outPutImage.frame.size.height/newCoordRect.imgHeight);
//assignment of the values after calculates coordinates
int x = newCoordRect.leftUp.x/(scaleX);
int y = newCoordRect.leftUp.y/(scaleY);
int heigth = ((newCoordRect.rightDown.y-newCoordRect.rightUp.y)/scaleY);
int width = ((newCoordRect.rightDown.x-newCoordRect.leftUp.x)/scaleX);
/* load image */
IplImage *img1 = [[ShareFunction sFunction]CreateIplImageFromUIImage:outPutImage.image];
/* sets the Region of Interest
Note that the rectangle area has to be __INSIDE__ the image */
cvSetImageROI(img1, cvRect(x, y, width, heigth));
/* create destination image
Note that cvGetSize will return the width and the height of ROI */
IplImage *img2 = cvCreateImage(cvGetSize(img1),
img1->depth,
3);
/* copy subimage */
cvCopy(img1, img2, NULL);
/* always reset the Region of Interest */
cvResetImageROI(img1);
retCropImg = [[ShareFunction sFunction]UIImageFromIplImage:img2];
any idea?

your code seems to be right.
Have a look at the orientation of the image

Related

SDL2 messed up image with manipulating pixels and SDL_UpdateTexture()

I'm trying to make a simple image viewer. I basically load an image into a surface and then create a texture from it.
At the end, I do the usual SDL_RenderClear(), SDL_RenderCopy() and SDL_RenderPresent() as per the migration guide.
This works fine, except that if I call SDL_UpdateTexture() before the 3 render calls above, I get a messed up image:
I am calling SDL_UpdateTexture() like this:
SDL_UpdateTexture(texture, NULL, image->pixels, image->pitch)
Where image is the surface I loaded for the image and texture is the texture I created from that. Attempts to vary the pitch result in differently messed up images. I also tried using a rect for the second parameter, but results are the same if the rect has the same dimensions as the image. If the dimensions are larger (e.g. same as the window), the update doesn't happen, but there are no errors.
The full code is available.
I would like to manipulate pixels of the surface directly via image->pixels and then call SDL_UpdateTexture(), but just calling SDL_UpdateTexture() without any tampering is enough to mess things up.
I think there is something wrong with the pitch or the SDL_Rect parameters,
but there is another SDL function which might help:
SDL_Texture* SDL_CreateTextureFromSurface(SDL_Renderer* renderer,
SDL_Surface* surface)
Could you maybe try the following. It should replace any pink (r=255,g=0,b=255) pixels to be transparent. You would simply change the pixel32 manipulation to accommodate your needs.
SDL_Surface* image = IMG_Load(filename);
SDL_Surface* imageFomatted = SDL_ConvertSurfaceFormat(image,
SDL_PIXELFORMAT_RGBA8888,
NULL);
texture = SDL_CreateTexture(renderer,
SDL_PIXELFORMAT_RGBA8888,
SDL_TEXTUREACCESS_STREAMING,
imageFomatted->w, imageFomatted->h);
void* pixels = NULL;
int pitch = 0;
SDL_LockTexture(texture, &imageFomatted->clip_rect, &pixels, &pitch);
memcpy(pixels, imageFomatted->pixels, (imageFomatted->pitch * imageFomatted->h));
int width = imageFomatted->w;
int height = imageFomatted->h;
Uint32* pixels32 = (Uint32*)pixels;
int pixelCount = (pitch / 4) * height;
Uint32 colorKey = SDL_MapRGB(imageFomatted->format, 0xFF, 0x00, 0xFF);
Uint32 transparent = SDL_MapRGBA(imageFomatted->format, 0xFF, 0x00, 0xFF, 0x00);
for (int i = 0; i < pixelCount; i++) {
if (pixels32[i] == colorKey) {
pixels32[i] = transparent;
}
}
SDL_UnlockTexture(texture);
SDL_FreeSurface(imageFormatted);
SDL_FreeSurface(image);
pixels = NULL;
pitch = 0;
width = 0;
height = 0;

openCV get subimage in C

I am using OpenCV for image manipulation in C. Please forgive me if this question is answered in the documentation, but I have found the OpenCV docs to be pretty badly formed and difficult to read.
I have an CvMat* that i have extracted from an image file as below:
CvMat* mat = cvLoadImageM((char*) filename, CV_LOAD_IMAGE_COLOR);
What I need to do is get a subimage of that by cropping out a certain bounded region. A logical command for this might be:
CvMat* subMat = cvGetSubImage(mat, minx, maxx, miny, maxy);
where minx, maxx, miny, and maxy define the boundaries of the cropped region. Is there a built in way to do this easily?
Take a look at http://nashruddin.com/OpenCV_Region_of_Interest_(ROI)/
In which the tutorial does the following on a Region of Interest:
cvSetImageROI(img1, cvRect(10, 15, 150, 250));
IplImage *img2 = cvCreateImage(cvGetSize(img1),
img1->depth,
img1->nChannels);
cvCopy(img1, img2, NULL);
cvResetImageROI(img1);
OpenCV has built in capabilities for setting the region which you care about and copying that region out of an image, just as you want to achieve.
If you want a sub-pixel accurate rectangular section of a src image use cvGetRectSubPix or cv::getRectSubPix (this creates an individual copy of all the data, this is not a ROI!)
Example:
cv::Size size(dst_width,dst_height);
cv::Point2f center(src_centerx,src_center_y);
cv::Mat dst;
cv::getRectSubPix(src,size, center,dst,CV_8U);
Generally this is done by cropping an ROI (region of interest). This blog post goes into some detail on cropping:
/* load image */
IplImage *img1 = cvLoadImage("elvita.jpg", 1);
/* sets the Region of Interest
Note that the rectangle area has to be __INSIDE__ the image */
cvSetImageROI(img1, cvRect(10, 15, 150, 250));
/* create destination image
Note that cvGetSize will return the width and the height of ROI */
IplImage *img2 = cvCreateImage(cvGetSize(img1),
img1->depth,
img1->nChannels);
/* copy subimage */
cvCopy(img1, img2, NULL);
/* always reset the Region of Interest */
cvResetImageROI(img1);
To convert between IplImage (legacy OpenCV) and cvMat (OpenCV 2.x), simply use the cvMat constructor or look at this question for more methods.

How to draw a rectangle in opencv dynamically according to image width and height?

i want to draw a rectangle in opencv according to the image width and height (i.e. i don't want to give a static values to cvRectangle) i want to draw a rectangle which covers most of the region of any image big or small in other words i want to draw the biggest rectangle in each image,thanks
May be, you'd like to use percentage dimensions?
IplImage *img=cvLoadImage(fileName,CV_LOAD_IMAGE_COLOR);
int imageWidth = img->width;
int imageHeight = img->height;
int imageSize = img->nSize;
int ratio = 90; // our ROI will be 90% of our input image
int roiWidth = (int)(imageWidth*ratio/100);
int roiHeight = (int)(imageHeight*ratio/100);
// offsets from image borders
int dw = (int) (imageWidth-roiWidth)/2;
int dh = (int) (imageHeight-roiHeight)/2;
cvRectangle(img,
cvPoint(dw,dh), // South-West point
cvPoint(roiWidth+dw, roiHeight+dh), // North-East point
cvScalar(0, 255, 0, 0),
1, 8, 0);
cvSetImageROI(img,cvRect(dw,dh,roiWidth,roiHeight));
So, now, If you set ratio = 90, and your input image is 1000x1000 pixels, than your ROI will be 900x900 pixels and it will be in the center of your image.
i have tried that and it works well
IplImage *img=cvLoadImage(fileName,CV_LOAD_IMAGE_COLOR);
int imageWidth=img->width-150;
int imageHeight=img->height-150;
int imageSize=img->nSize;
cvRectangle(img,cvPoint(imageWidth,imageHeight), cvPoint(50, 50),cvScalar(0, 255, 0, 0),1,8,0);
cvSetImageROI(img,cvRect(50,50,(imageWidth-50),(imageHeight-50)));

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.

How would I map a camera image to create a live funhouse mirror using opencv?

Using Opencv and Linux I would like to create a fun-house mirror effect, short and squat, tall and thin effect using a live webcamera. My daughter loves those things and I would like to create one using a camera. I am not quite sure about the transforms necessary for these effects. Any help would be appreciated. I have much of the framework running, live video playing and such, just not the transforms.
thanx
I think that you need to use 'radial' transforms and 'pin cushion' which is inverse radial.
In order to braker the symmetry of the transforms you can strech the image before and after:
Suppose your image is 300x300
pixels.
Strech it to 300x600 or
600x300 using cvResize()
Apply transform: radial, pincushion or
sinusoidal
Strech back to 300x300
I never used radial or sinusoidal transforms in openCV so I dont have a piece of code to attach. But you can use cvUndistort2() and see if it is OK.
Create window with trackbars with range 0..100. Each trackbar controls parameter of distortion:
static IplImage* srcImage;
static IplImage* dstImage;
static double _camera[9];
static double _dist4Coeff[4]; // This is the transformation matrix
static int _r = 50; // Radial transform. 50 in range 0..100
static int _tX = 50; // Tangetial coef in X directio
static int _tY = 50; // Tangetial coef in Y directio
static int allRange = 50;
// Open windows
cvNamedWindow(winName, 1);
// Add track bars.
cvShowImage(winName, srcImage );
cvCreateTrackbar("Radial", winName, &_r , 2*allRange, callBackFun);
cvCreateTrackbar("Tang X", winName, &_tX , 2*allRange, callBackFun);
cvCreateTrackbar("Tang Y", winName, &_tY , 2*allRange, callBackFun);
callBackFun(0);
// The distortion call back
void callBackFun(int arg){
CvMat intrCamParamsMat = cvMat( 3, 3, CV_64F, _camera );
CvMat dist4Coeff = cvMat( 1, 4, CV_64F, _dist4Coeff );
// Build distortion coefficients matrix.
dist4Coeff.data.db[0] = (_r-allRange*1.0)/allRange*1.0;
dist4Coeff.data.db[1] = (_r-allRange*1.0)/allRange*1.0;
dist4Coeff.data.db[2] = (_tY-allRange*1.0)/allRange*1.0;
dist4Coeff.data.db[3] = (_tX-allRange*1.0)/allRange*1.0;
// Build intrinsic camera parameters matrix.
intrCamParamsMat.data.db[0] = 587.1769751432448200/2.0;
intrCamParamsMat.data.db[1] = 0.;
intrCamParamsMat.data.db[2] = 319.5000000000000000/2.0+0;
intrCamParamsMat.data.db[3] = 0.;
intrCamParamsMat.data.db[4] = 591.3189722549362800/2.0;
intrCamParamsMat.data.db[5] = 239.5000000000000000/2.0+0;
intrCamParamsMat.data.db[6] = 0.;
intrCamParamsMat.data.db[7] = 0.;
intrCamParamsMat.data.db[8] = 1.;
// Apply transformation
cvUndistort2( srcImage, dstImage, &intrCamParamsMat, &dist4Coeff );
cvShowImage( winName, dstImage );
}

Resources