How can i use cvGet2D and cvSet2D to get this result:
Code:
std::string path = "C:\\image.jpg";
cv::Mat img = cv::imread (path);
CvScalar scal = cvGet2D(m, 0, 2);
cvSet2D(m, 0, 2, new_value);*/
cv::imshow( "Result window", img );
Since you know the coordinates of the top-left and bottom-right rectangle corners:
Point tl(250, 250);
Point br(350, 280);
You can draw a black filled rectangle:
rectangle(img, Rect(tl, br), Scalar(0,0,0), CV_FILLED);
Result (note that my image has different size from yours, so results appear slightly different):
Code:
#include <opencv2\opencv.hpp>
using namespace cv;
int main()
{
// Load image
Mat3b img = imread("path_to_image");
// Set top-left and bottom-right rectangle points
Point tl(250, 250);
Point br(350, 280);
// Draw a filled rect
rectangle(img, Rect(tl, br), Scalar(0,0,0), CV_FILLED);
// Show result
imshow("Result", img);
waitKey();
return 0;
}
Note
cvSetXD and cvGetXD are old style C syntax. You should never mix obsolete C syntax and C++ syntax. If you want to access pixel values in a Mat, you should use the at function.
Related
I use openCV to recognize contours. Now I want to create a new binary mat containing all coordinates of this contour.
Canny edge detection applied
found contour's (red one is the one I'd like to use)
just coordinates inside contour are drawn into new mat
This is what I've got so far:
vector<cv::Point> contour; // red marked contour;
cv::Rect boundingBox = cv::boundingRect(contour);
Mat newMat;
vector<cv::Point> insideContour;
for (int i=0; i<contour.size(); i++) {
// get all coordinates inside of contour
// insideContour.push_back(?)
}
for (int y=0; y<boundingBox.height; y++) {
for (int x=0; x<boundingBox.width; x++) {
// newMat
}
}
Any help how to go on would be really appreciated because I'm absolutely clueless.
Try this. For simplicity cv::Point(250, 219) is a point inside the red contour, use Haar to find bounding box and it's center in reality.
cv::Mat image = imread("Smiley.jpg");
cv::Mat image2 = imread("Smiley2.jpg");
// subtract images and floodfill to prepare red mask
Mat red_contour, red_mask, maskMat, outputMat;
subtract(image2, image, red_contour);
threshold(red_contour, red_mask, 100, 255, THRESH_BINARY);
int filling = cv::floodFill(red_mask, cv::Point(250, 219), cv::Scalar(0, 0, 255), (cv::Rect*)0, cv::Scalar(), cv::Scalar(), 4);
//prepare a grey mask
cv::cvtColor(red_mask, maskMat, CV_BGR2GRAY);
threshold(maskMat, maskMat, 0, 255, THRESH_BINARY);
// use mask to crop original image
image.copyTo(outputMat, maskMat);
cv::namedWindow("Image");
cv::imshow("Image", outputMat);
cv::waitKey();
return 0;
SSorry for my bad english . I have an image that Show 3 circles of different color, one red, one green and one blue and I can display this image into the 3 channels, but they appear white and in the code I display an image call "copy R" and I dont know how to make this copy R into another image whit any color I want to overlap the original image and changing the red color. How can i do this ???
this is my code, sorry is the first time i make a question and dont know how to publish properly
#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#define w 400
using namespace cv;
/// Function headers
void MyFilledCircle(Mat img, Point center);
void MyFilledCircle1(Mat img, Point center);
void MyFilledCircle2(Mat img, Point center);
int main(void) {
//![create_images]
char window[] = "Original";
/// Create black empty images
Mat image = Mat::zeros(w, w, CV_8UC3);
/// 1.b. Creating circles
MyFilledCircle(image, Point(200, 200));
MyFilledCircle1(image, Point(150, 150));
MyFilledCircle2(image, Point(250, 250));
Mat channel[3];
split(image, channel);
//channel[0] = Mat::zeros(image.rows, image.cols, CV_8UC1);
merge(channel, 3, image);
Mat imageHSV;
Mat copy;
imshow(window, image);
//imshow("Color 1", imageHSV);
inRange(image, Scalar(0, 0, 255), Scalar(0, 0, 255), copy);
imshow("copy R", copy);
imshow("B", channel[0]);
imshow("G", channel[1]);
imshow("R", channel[2]);
//imshow("0", canal0);
//imwrite("dest.jpg", image);
waitKey(0);
return(0);
}
/// Function Declaration
//![myfilledcircle]
void MyFilledCircle1(Mat img, Point center)
{
circle(img,
center,
50,
Scalar(0, 255, 0),
FILLED,
LINE_8);
}
void MyFilledCircle(Mat img, Point center)
{
circle(img,
center,
50,
Scalar(0, 0, 255),
FILLED,
LINE_8);
}
void MyFilledCircle2(Mat img, Point center)
{
circle(img,
center,
50,
Scalar(255, 0, 0),
FILLED,
LINE_8);
}
From the looks of it, it looks like copy is a binary mask, and you want to superimpose this mask on image, such that only the non-zero pixels in the mask retain their original color.
If my assumption is correct, then using the subtract method, as shown below, should help you out:
Mat result;
cvtColor(copy,copy,CV_GRAY2BGR);//change copy to a 3 channel image
absdiff(image,image,result);//initialize mask as a black image of img.size()
subtract(copy,image,result);
subtract(copy,result,result);
Im trying to detect the pallet in forklift. but find contours cant detect the rectangle in a correct way.
how can I detect the large pallet.
I have tried hough transform but it fails of detecting the forklift rectangle, so I'm using findcontours instead.
pallet
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
int main()
{
cv::Mat input = cv::imread("pallet.jpg");
// convert to grayscale (you could load as grayscale instead)
cv::Mat gray;
cv::cvtColor(input,gray, CV_BGR2GRAY);
// compute mask (you could use a simple threshold if the image is always as good as the one you provided)
cv::Mat mask;
cv::threshold(gray, mask, 0, 255, CV_THRESH_BINARY_INV | CV_THRESH_OTSU);
// find contours (if always so easy to segment as your image, you could just add the black/rect pixels to a vector)
std::vector<std::vector<cv::Point> > contours;
std::vector<cv::Vec4i> hierarchy;
cv::findContours(mask,contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);
/// Draw contours and find biggest contour (if there are other contours in the image, we assume the biggest one is the desired rect)
// drawing here is only for demonstration!
int biggestContourIdx = -1;
float biggestContourArea = 0;
cv::Mat drawing = cv::Mat::zeros( mask.size(), CV_8UC3 );
for( int i = 0; i< contours.size(); i++ )
{
cv::Scalar color = cv::Scalar(0, 100, 0);
drawContours( drawing, contours, i, color, 1, 8, hierarchy, 0, cv::Point() );
float ctArea= cv::contourArea(contours[i]);
if(ctArea > biggestContourArea)
{
biggestContourArea = ctArea;
biggestContourIdx = i;
}
}
// if no contour found
if(biggestContourIdx < 0)
{
std::cout << "no contour found" << std::endl;
return 1;
}
// compute the rotated bounding rect of the biggest contour! (this is the part that does what you want/need)
cv::RotatedRect boundingBox = cv::minAreaRect(contours[biggestContourIdx]);
// one thing to remark: this will compute the OUTER boundary box, so maybe you have to erode/dilate if you want something between the ragged lines
// draw the rotated rect
cv::Point2f corners[4];
boundingBox.points(corners);
cv::line(drawing, corners[0], corners[1], cv::Scalar(255,255,255));
cv::line(drawing, corners[1], corners[2], cv::Scalar(255,255,255));
cv::line(drawing, corners[2], corners[3], cv::Scalar(255,255,255));
cv::line(drawing, corners[3], corners[0], cv::Scalar(255,255,255));
// display
cv::imshow("input", input);
cv::imshow("drawing", drawing);
cv::waitKey(0);
cv::imwrite("rotatedRect.png",drawing);
return 0;
}
I'm trying to move a region of an image to the center, I succeeded in getting its contour and I know how to place this in the center.
But what I want is to move the pixels that are inside the contour (yellow with black) at the center and not just the contour (which is pink by CV_FILLED).
Image:
Code:
//Then segment the image. save in Mat crop
// ---- Center image -----
// pos : contour interest
RotatedRect rr = fitEllipse(contours[pos]);
vector<Point>&contour = contours[pos];
//http://stackoverflow.com/a/29467236/4595387
//difference between the centre of the image and centre of the contour
Point center = Point( crop.cols/2, crop.rows/2 );
int nX = center.x - rr.center.x;
int nY = center.y - rr.center.y;
for (size_t i=0; i< contour.size(); i++)
{
contour[i].x += nX;
contour[i].y += nY;
}
cout << "x: " << rr.center.x;
cout << "y: " << rr.center.y;
//color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
//contour of the image to the center.
cv::drawContours(crop, contours, pos, color, CV_FILLED);
imshow("In",imagen_src);
imshow("Out",crop);
You need basically to play around with copyTo with a mask. The steps are commented in the code. If you need a different background color, just change backgroundColor in the code below.
Code:
#include <opencv2\opencv.hpp>
using namespace cv;
int main()
{
// Read image
Mat3b img = imread("path_to_image");
// Convert to hsv
Mat3b hsv;
cvtColor(img, hsv, COLOR_BGR2HSV);
// Threshold on yellow color (in hsv space)
Mat1b maskOnYellow;
inRange(hsv, Scalar(20, 100, 100), Scalar(40, 255, 255), maskOnYellow);
// Find contours of yellow item
vector<vector<Point>> contours;
findContours(maskOnYellow.clone(), contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);
// Create a mask as a filled contour
Mat1b mask(img.rows, img.cols, uchar(0));
drawContours(mask, contours, 0, Scalar(255), CV_FILLED);
// Get the bounding box of the item
Rect box = boundingRect(contours[0]);
// Get the roi in the input image according to the mask
Mat3b item(img(box));
// Create a black image (same size as the yellow item and same background bolor as result image)
// to copy the result of the segmentation
Vec3b backgroundColor(0,0,0); // black
Mat3b segmentedItem(item.rows, item.cols, backgroundColor);
// Copy only the masked part
item.copyTo(segmentedItem, mask(box));
// Compute the center of the image
Point center(img.cols / 2, img.rows / 2);
// Create a result image
Mat3b res(img.rows, img.cols, backgroundColor);
// Compute the rectangle centered in the image, same size as box
Rect centerBox(center.x - box.width/2, center.y - box.height/2, box.width, box.height);
// Put the segmented item in the center of the result image
segmentedItem.copyTo(res(centerBox));
imshow("Result", res);
waitKey();
return 0;
}
Input:
Result:
So I've been working on recognizing a yoga ball with Hough Circles. Now, when converted to grayscale, it works straight away. Unfortunately, I have to take a more complicated procedure due to there being multiple of these coloured balls and only wanted to detect the blue.
Unfiltered ball:
Filtered ball:
Steps of my algorithm:
convert from BGR to HSV
blur the image
filter HSV for only select values (in my case dark blue to light blue due to lighting)
invert the image
use morphology to fill in the part that was lighted
blur again
filter the blur so it's a solid shape instead of unrecognisable blurry grayscale
detect with hough-circles. The MAT is still Grayscale so that isn't the problem.
Code:
#include <iostream>
#include <string>
#include <iomanip>
#include <sstream>
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
using namespace std;
using namespace cv;
int main(int argc, char *argv[])
{
// Morphology stuff
Mat element5(30, 30, CV_8U, Scalar(1));
int morph_elem = 1; // 2
int morph_size = 33;// 30
int morph_operator = 2; // 2
Mat element = getStructuringElement(morph_elem, Size(2 * morph_size + 1, 2 * morph_size + 1), Point(morph_size, morph_size));
int const max_operator = 4;
int const max_elem = 2;
int const max_kernel_size = 21;
Mat kernel;
// Display Windows Name
namedWindow("Testing Purposes", CV_WINDOW_AUTOSIZE);
Mat src; // loaded image
Mat hsv; // changed src into HSV
Mat Filtered; // filtered w/ inRange for blue ball
Mat Gray; // gray filter for src
Mat dst; // destination for canny edge
Mat detected_edges; // matrix of edges w/ canny
// thresholds for canny
int edgeThresh = 45;
int lowThreshold;
int const max_lowThreshold = 100;
src = imread(argv[1]);
cvtColor(src, Gray, CV_BGR2GRAY);
cvtColor(src, hsv, CV_BGR2HSV);
/*
// CannyEdge Testing
blur(Gray, detected_edges, Size(3, 3)); // blur the grayimage
Canny(detected_edges, detected_edges, lowThreshold, lowThreshold * ratio, kernel_size);
dst = Scalar::all(0);
src.copyTo( dst, detected_edges);
imshow(window_name,dst);
*/
// hsv blur and then thresholds
blur(hsv,hsv,Size(4, 4), Point(-1, -1));
inRange(hsv, Scalar(100, 100, 0), Scalar(200, 200, 255), Filtered); //filtering after blur
vector<Vec3f> circles; //vector for holding info on circles
// houghcircles - attempts to detect circles in the Filtered image we passed it
// morphology defintion for Kernel
bitwise_not(Filtered, Filtered);
// imwrite("/home/bjacobs/Desktop/Testing.jpg", Filtered);
imwrite("/home/bjacobs/Desktop/Testingg.jpg", Filtered);
morphologyEx(Filtered, dst, MORPH_OPEN, element);
blur(dst, dst, Size(20, 20), Point(-1, -1));
Mat baw = dst > 128;
HoughCircles(baw ,circles, CV_HOUGH_GRADIENT, 1, baw.rows/8,200,100,0,0);
imwrite("/home/bjacobs/Desktop/Testing.jpg", baw);
// Draw the circles detected onto the SRC file
for(size_t i = 0; i < circles.size(); i++)
{
Point center(cvRound(circles[i][0]), cvRound(circles[i][3]));
int radius = cvRound(circles[i][2]);
// circle center
circle(src, center, 3, Scalar(0, 255, 0), -1, 8, 0);
// circle outline
circle(src, center, radius, Scalar(0, 0, 255), 3, 8, 0);
}
imwrite("/home/bjacobs/Desktop/Test.jpg", hsv);
imshow("Testing Purposes", src);
waitKey(0);
}
I've already read as much as I possibly could online on this matter, and nothing I've found so far has helped. Forgive the sloppy commenting, and there are some failed algorithms included with using Canny Edge detection, so don't pay too much mind to them. Does anyone know of a solution to this detection issue?
Instead of using houghcircle you can do the following.
Segment the blue color.
Find contours(largest).
Minimum enclosing circle for contour.