Can s.o help to translate this code to ruby-openvc?
Original
http://aishack.in/tutorials/tracking-colored-objects-in-opencv/
IplImage* GetThresholdedImage(IplImage* img)
{
#Convert the image into an HSV image
IplImage* imgHSV = cvCreateImage(cvGetSize(img), 8, 3);
cvCvtColor(img, imgHSV, CV_BGR2HSV);
#create a new image that will hold the threholded image (which will be returned).
IplImage* imgThreshed = cvCreateImage(cvGetSize(img), 8, 1);
#Now we do the actual thresholding:
cvInRangeS(imgHSV, cvScalar(20, 100, 100), cvScalar(30, 255, 255), imgThreshed)
cvReleaseImage(&imgHSV);
return imgThreshed;
}
Translated
def getThresholdedImage2 (img)
#blur the source image to reduce color noise
img = img.smooth(CV_GAUSSIAN, 7, 7)
#convert the image to hsv(Hue, Saturation, Value) so its
#easier to determine the color to track(hue) imgHSV = IplImage.new(img.width, img.height, 8, 3);
imgHSV = img.BGR2HSV
#create a new image that will hold the threholded image (which will be returned).
imgThreshed = IplImage.new(img.width, img.height, 8, 1);
#Now we do the actual thresholding:
imgThreshed = imgHSV.in_range(CvScalar.new(20, 100, 100), CvScalar.new(30, 255, 255));
return imgThreshed
end
Actally, I don't know ruby at all but it seems that I found solution to your problem. Ruby-OpenCV seems to be just a library-wrapper.
For example, if you want to find analogue of cvInRangeS function you should do the following.
By searching in source files I found ext/opencv/cvmat.h with this content:
VALUE rb_range(VALUE self, VALUE start, VALUE end);
VALUE rb_range_bang(VALUE self, VALUE start, VALUE end);
And in the cpp file there's description:
/*
* call-seq:
* in_range(<i>min, max</i>) -> cvmat
*
* Check that element lie between two object.
* <i>min</i> and <i>max</i> should be CvMat that have same size and type, or CvScalar.
* Return new matrix performed per-element,
* dst(I) = within the range ? 0xFF : 0
*/
So you should find all needed ruby functions by this way. Good luck!
Related
I'm trying to change the brightness of an image in Flash. I have converted the flash to a bitmap, and would like to make a button that increases or decreases the brightness of the image as a whole. Is there a way to access every pixel in the image at once to do this (using code, not the Panels on Stage)?
Using the ColorMatrixFilter class, you can adjust the brightness by applying the same multiplier to each color channel.
So something like this (from this source):
image.filters = [makeBrightFilter(50)];
function makeBrightFilter(amount):ColorMatrixFilter {
amount = amount * (255/250);
var m:Array = new Array();
m = m.concat([1, 0, 0, 0, amount]); // red
m = m.concat([0, 1, 0, 0, amount]); // green
m = m.concat([0, 0, 1, 0, amount]); // blue
m = m.concat([0, 0, 0, 1, 0]); // alpha
return new ColorMatrixFilter(m);
}
To abstract it out and make it even easier, you could use a library like Grant Skinner's ColorMatrix class.
Then you do something like this:
import com.gskinner.geom.ColorMatrix;
import flash.filters.ColorMatrixFilter;
var matrix:ColorMatrix = new ColorMatrix();
matrix.adjustBrightness(50);
image.filters = [new ColorMatrixFilter(matrix)];
I am trying to detect doctor's tools from endoscopy video using the following code
static void video_tracking(){
//read image
IplImage orgImg = cvLoadImage("C:/Users/Ioanna/Desktop/pic.png");
IplImage thresholdImage = hsvThreshold(orgImg);
cvSaveImage("hsvthreshold.jpg", thresholdImage);
Dimension position = getCoordinates(thresholdImage);
System.out.println("Dimension of original Image : " + thresholdImage.width() + " , " + thresholdImage.height());
System.out.println("Position of red spot : x : " + position.width + " , y : " + position.height);
}
static Dimension getCoordinates(IplImage thresholdImage) {
int posX = 0;
int posY = 0;
CvMoments moments = new CvMoments();
cvMoments(thresholdImage, moments, 1);
double momX10 = cvGetSpatialMoment(moments, 1, 0); // (x,y)
double momY01 = cvGetSpatialMoment(moments, 0, 1);// (x,y)
double area = cvGetCentralMoment(moments, 0, 0);
posX = (int) (momX10 / area);
posY = (int) (momY01 / area);
return new Dimension(posX, posY);
}
static IplImage hsvThreshold(IplImage orgImg) {
// Convert the image into an HSV image
IplImage imgHSV = cvCreateImage(cvGetSize(orgImg), 8, 3);
cvCvtColor(orgImg, imgHSV, CV_BGR2HSV);
//create a new image that will hold the threholded image
// 1- color = monochrome
IplImage imgThreshold = cvCreateImage(cvGetSize(orgImg), orgImg.depth(), 1);
//do the actual thresholding
cvInRangeS(imgHSV, cvScalar(13, 0, 0, 0), cvScalar(40, 117, 124, 88), imgThreshold);
cvReleaseImage(imgHSV);
cvSmooth(imgThreshold, imgThreshold, CV_MEDIAN, 13);
// save
return imgThreshold;
}
The input of the above code is a color image with 2 doctor's object and the output is a grayscale image that detect the tools. Sorry, but the system doesn't allow to upload the images.
The problem is I don't know how to find the position of 2 tools and draw a rectangle. Please can some one explain how to archive my objective using javacv/opencv?
It can be achieve using Haar Casacde files .Some of the bulit-In Haar files provided by google can found in opencv\data\haarcascades directory .These files are XML files generated by heavy training sections.Some of the sample haar files are used for face detection,ear detection etc.A sample project can be fount at here.You can generate your own haar cascade file for any purpose.one of the method for generate Haar cascade file can be found at here
I have tried this code. 540 is the left most x value of the box,3 is left most y value of the box,262 - width ,23 -height of the region which I am going to calculate the ratio of the white/black pixels. What I really wanted to do is detect the number of white/black pixel ratio in a specific region.I have calculate the coordinates for each cell (regions which I am going to specified)and try with this code.But the error in counting.
Can I please have an idea about this issue please..
I am really stuck here with my final year project.
CvSize cvSize = cvSize(img.width(), img.height());
IplImage image = cvCreateImage(cvSize, IPL_DEPTH_8U, 1);
IplImage image2 = cvCreateImage(cvSize, IPL_DEPTH_8U, 3);
cvCvtColor(image2, image, CV_RGB2GRAY);
cvSetImageROI(image2, cvRect(540,3,262,23));
//IplImage image2 = cvCreateImage(cvSize, IPL_DEPTH_8U, 3);
//
//cvCvtColor(arg0, arg1, arg2)
// cvCvtColor(image2, image, CV_RGB2GRAY);
//cvThreshold(image, image, 128, 255, CV_THRESH_BINARY);
CvLineIterator iterator = new CvLineIterator();
double sum = 0, green_sum = 0, red_sum = 0;
CvPoint p2 = new CvPoint(802,3);
CvPoint p1 = new CvPoint(540,26);
int lineCount = cvInitLineIterator(image2, p1, p2, iterator, 8, 0 );
for (int i = 0; i < lineCount; i++) {
sum += iterator.ptr().get() & 0xFF;
}
System.out.println("sum................"+sum);
CV_NEXT_LINE_POINT(iterator);
}
}
it gave the result as sum................0.0
I have really stuck with this..can you please give any solution for this issue please
Move CV_NEXT_LINE_POINT(iterator); line inside the for loop. Then it should work.
I am learning HTML5 and JavaScript and am attempting to draw an animated image. I thought the easiest way to do this would be to create an image with the frames in a row, as below.
Image http://html5stuff.x10.mx/HTML5%20Test/alien_green_strip8.png
Then a only part of the image would be draw at a time. I followed this tutorial.
This is a link to what I have made:
html5stuff.x10.mx/HTML5%20Test/page.html
The problem is, the image isn't being drawn. It's something within the drawSprite function, because when I change it to a simple "ctx.drawImage(sprite.source, x, y)", it does draw the image (just as a whole without the animation, obviously). Please note that though there is an option for rotating the image, I have not yet added support for that. Also, keys.js is not being used yet though it is included.
The reason is because sprite.imagenum is not defined when drawSprite is called.
This is because in some places you use imagenum and others imgnum, so correct that typo and you're good to go!
TOTALLY OPTIONAL:
But now that thats answered lets take a look at your js to get a better idea of how to structure this. You have:
function Sprite(){
var imagenum = null; //The number of images
var width = null; //The width of each image
var height = null; //The height on each image
var xoffset = null; //The origin on each image
var yoffset = null;
var source = null; //The location of each image
}
function drawSprite(sprite, subimg, x, y, w, h, angle){
ctx.drawImage(sprite.source, Math.floor(subimg) * sprite.width, 0, w * sprite.imagenum, h, x - sprite.xoffset * (w/sprite.width), y - sprite.yoffset * (h/sprite.height), w, h);
}
All those var statements are actually doing nothing. It should be:
function Sprite(){
this.imagenum = null; //The number of images
this.width = null; //The width of each image
this.height = null; //The height on each image
this.xoffset = null; //The origin on each image
this.yoffset = null;
this.source = null; //The location of each image
}
in order to correctly set them as you were envisioning. Also, you can rewrite drawSprite so that the sprites are drawing themselves, so that you don't need to pass them as an argument:
// now we can use "this" instead of "sprite"
Spite.prototype.draw = function(subimg, x, y, w, h, angle){
// put this on several lines just so we can see it easier
ctx.drawImage(this.source,
Math.floor(subimg) * this.width,
0,
w * this.imagenum, h,
x - this.xoffset * (w/this.width),
y - this.yoffset * (h/this.height),
w, h);
}
Then instead of:
drawSprite(img, index, 128, 128, 32, 32, 0); // img is a sprite
We can write:
img.draw(index, 128, 128, 32, 32, 0); // img is a sprite
I'm trying to detect circles but I am detecting circles that aren't even there. My code is below. Anyone know how to modify the DetectCircle() method to make the detection more accurate , please and thanks
void detectCircle( IplImage * img )
{
int edge_thresh = 1;
IplImage *gray = cvCreateImage( cvSize(img->width,img->height), 8, 1);
IplImage *edge = cvCreateImage( cvSize(img->width,img->height), 8, 1);
cvCvtColor(img, gray, CV_BGR2GRAY);
gray->origin = 1;
// color threshold
cvThreshold(gray,gray,100,255,CV_THRESH_BINARY);
// smooths out image
cvSmooth(gray, gray, CV_GAUSSIAN, 11, 11);
// get edges
cvCanny(gray, edge, (float)edge_thresh, (float)edge_thresh*3, 5);
// detects circle
CvSeq* circle = cvHoughCircles(edge, cstorage, CV_HOUGH_GRADIENT, 1,
edge->height/50, 5, 35);
// draws circle and its centerpoint
float* p = (float*)cvGetSeqElem( circle, 0 );
if( p==null ){ return;}
cvCircle( img, cvPoint(cvRound(p[0]),cvRound(p[1])), 3, CV_RGB(255,0,0), -1, 8, 0 );
cvCircle( img, cvPoint(cvRound(p[0]),cvRound(p[1])), cvRound(p[2]), CV_RGB(200,0,0), 1, 8, 0 );
cvShowImage ("Snooker", img );
}
cvHoughCircles detects circles that arent obvious to us. If you know the pixel size of snooker balls you can filter them based on their radius. Try setting the min_radius and max_radius parameters in your cvHoughCircles function.
On a side note, once you get the circles, you can filter them based on color. If the circle is mostly one color, it has a good chance of being a ball, if it doenst its probably a false positive.
edit: by "circle's color" i mean the pixels inside the circle boundary