hey i want to do a linear gray transformation, so that i can change the contrast.
how i can get the maximum and minimum gray value ? and then i want to scale the Image that it has a limited contrast range of 100 to 150. I have searched like 2 hours but dont found something.
would be nice if someone could help
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
#include <opencv2/imgproc.hpp>
using namespace std;
using namespace cv;
cv::Mat plotHistogram(cv::Mat &image, bool cumulative = true, int histSize = 256);
int main()
{
cv::Mat img = cv::imread(schrott.png"); // Read the file
if (img.empty()) // Check for invalid input
{
std::cout << "Could not open or find the frame" << std::endl;
return -1;
}
cv::Mat img_gray;
cv::cvtColor(img, img_gray, cv::COLOR_BGR2GRAY); // In case img is colored
cv::namedWindow("Input Image", cv::WINDOW_AUTOSIZE); // Create a window for display.
cv::imshow("Input Image", img);
cv::Mat hist;
hist = plotHistogram(img_gray);
cv::namedWindow("Histogram", cv::WINDOW_NORMAL); // Create a window for display.
cv::imshow("Histogram", hist);
cv::waitKey(0);
}
cv::Mat plotHistogram(cv::Mat &image, bool cumulative, int histSize) {
// Create Image for Histogram
int hist_w = 1024; int hist_h = 800;
int bin_w = cvRound((double)hist_w / histSize);
cv::Mat histImage(hist_h, hist_w, CV_8UC1, Scalar(255, 255, 255));
if (image.channels() > 1) {
cerr << "plotHistogram: Please insert only gray images." << endl;
return histImage;
}
// Calculate Histogram
float range[] = { 0, 256 };
const float* histRange = { range };
cv::Mat hist;
calcHist(&image, 1, 0, Mat(), hist, 1, &histSize, &histRange);
if (cumulative) {
cv::Mat accumulatedHist = hist.clone();
for (int i = 1; i < histSize; i++) {
accumulatedHist.at<float>(i) += accumulatedHist.at<float>(i - 1);
}
hist = accumulatedHist;
}
// Normalize the result to [ 0, histImage.rows ]
normalize(hist, hist, 0, histImage.rows, NORM_MINMAX, -1, Mat());
// Draw bars
for (int i = 1; i < histSize; i++) {
cv::rectangle(histImage, Point(bin_w * (i - 1), hist_h),
Point(bin_w * (i), hist_h - cvRound(hist.at<float>(i))),
Scalar(50, 50, 50), 1);
}
return histImage; // Not really call by value, as cv::Mat only saves a pointer to the image data
}
You can find minimum and maximum value with minMaxLoc
Mat image;
//read image;
double min, max;
minMaxLoc( image, &min, &max );
cout << "min : " << min << "max : " << max << endl;
Related
I am trying to take out the ground and make grids on it for path mapping and insert it back to the image. Here I am using findhomography and warpPerspective functions to do so. But when I switch the points for inserting back the modified plane, everything except the plane becomes black in the image.
I have tried to do it using an intermediate image but the result is the same.
#include "pch.h"
#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;
struct userdata {
Mat im;
vector<Point2f> points;
};
void mouseHandler(int event, int x, int y, int flags, void* data_ptr)
{
if (event == EVENT_LBUTTONDOWN) {
userdata* data = ((userdata*)data_ptr);
circle(data - > im, Point(x, y), 3, Scalar(0, 0, 255), 5, LINE_AA);
imshow("Image", data - > im);
if (data - > points.size() < 4) {
data - > points.push_back(Point2f(x, y));
}
}
}
int main(int argc, char** argv)
{
// Read source image.
Mat im_src = imread("imagesindoor.jpg");
// Destination image. The aspect ratio of the book is 3/4
Size size(400, 300);
Size size2(im_src.cols, im_src.rows);
Mat im_dst = Mat::zeros(size, CV_8UC3);
// Create a vector of destination points.
vector<Point2f> pts_dst;
pts_dst.push_back(Point2f(0, 0));
pts_dst.push_back(Point2f(size.width - 1, 0));
pts_dst.push_back(Point2f(size.width - 1, size.height - 1));
pts_dst.push_back(Point2f(0, size.height - 1));
// Set data for mouse event
Mat im_temp = im_src.clone();
userdata data;
data.im = im_temp;
cout << "Click on the four corners of the book -- top left first and" <<
endl
<< "bottom left last -- and then hit ENTER" << endl;
// Show image and wait for 4 clicks.
imshow("Image", im_temp);
// Set the callback function for any mouse event
setMouseCallback("Image", mouseHandler, &data);
waitKey(0);
// Calculate the homography
Mat h = getPerspectiveTransform(data.points, pts_dst);
// Warp source image to destination
warpPerspective(im_src, im_dst, h, size);
// changing clor of im_dst
for (int i = 0; i < im_dst.rows; i++) {
for (int j = 0; j < im_dst.cols; j++) {
//apply condition here
im_dst.at<cv::Vec3b>(i, j) = 255;
}
}
Mat p = getPerspectiveTransform(pts_dst, data.points);
warpPerspective(im_dst, im_src, p, size2);
// Show image
//imshow("Image", im_dst);
imshow("Image2", im_src);
waitKey(0);
return 0;
}
addWeighted can be used to blend the current result with the source image to get the expected result.
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <opencv2/opencv.hpp>
#include <iostream>
#include <stdio.h>
using namespace cv;
using namespace std;
struct userdata {
Mat im;
vector<Point2f> points;
};
void mouseHandler(int event, int x, int y, int flags, void* data_ptr)
{
if (event == EVENT_LBUTTONDOWN) {
userdata* data = ((userdata*)data_ptr);
circle(data-> im, Point(x, y), 3, Scalar(0, 0, 255), 5, LINE_AA);
imshow("Image", data->im);
if (data-> points.size() < 4) {
data-> points.push_back(Point2f(x, y));
}
}
}
int main(int argc, char** argv)
{
// Read source image.
Mat im_src = imread("test.png");
// Destination image. The aspect ratio of the book is 3/4
Size size(400, 300);
Size size2(im_src.cols, im_src.rows);
Mat im_dst = Mat::zeros(size, CV_8UC3);
// Create a vector of destination points.
vector<Point2f> pts_dst;
pts_dst.push_back(Point2f(0, 0));
pts_dst.push_back(Point2f(size.width - 1, 0));
pts_dst.push_back(Point2f(size.width - 1, size.height - 1));
pts_dst.push_back(Point2f(0, size.height - 1));
// Set data for mouse event
Mat im_temp = im_src.clone();
userdata data;
data.im = im_temp;
cout << "Click on the four corners of the book -- top left first and" <<
endl
<< "bottom left last -- and then hit ENTER" << endl;
// Show image and wait for 4 clicks.
imshow("Image", im_temp);
// Set the callback function for any mouse event
setMouseCallback("Image", mouseHandler, &data);
waitKey(0);
// Calculate the homography
Mat h = getPerspectiveTransform(data.points, pts_dst);
// Warp source image to destination
warpPerspective(im_src, im_dst, h, size);
// changing clor of im_dst
for (int i = 0; i < im_dst.rows; i++) {
for (int j = 0; j < im_dst.cols; j++) {
//apply condition here
im_dst.at<cv::Vec3b>(i, j) = 255;
}
}
Mat t;
Mat p = getPerspectiveTransform(pts_dst, data.points);
warpPerspective(im_dst, t, p, size2);
// Show image
//imshow("Image", im_dst);
std::cout << "t :" <<t.cols << ", " <<t.rows <<std::endl;
Mat final;
addWeighted(im_src, 0.5, t, 0.5, 0, final);
imshow("Image2", final);
waitKey(0);
return 0;
}
I'm trying to calculate the mass center of images using OpenCV and I got errors, as you can see in the images (the mass center must not be to closest of any side in this cases). Also, I got mass centers that depends of the rotation and that's incorrect.
Next, you can see the code, input image and output image.
I tried with different example codes, and the results are the same.
Output image: Mass center calculated by the program
Input image: Image Input
Example code:
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
using namespace cv;
using namespace std;
Mat src; Mat srcGray;
RNG rng(12345);
int main(int argc, char **argv)
{
// Load source image and convert it to gray
src = imread(argv[1], 1);
// Convert image to gray and blur it
cvtColor(src, srcGray, CV_BGR2GRAY);
blur(srcGray, srcGray, Size(3, 3));
Mat srcThresh;
double otsu;
otsu = threshold(srcGray, srcThresh, 0, 255, CV_THRESH_BINARY | CV_THRESH_OTSU);
Mat cannyOut;
Canny(srcGray, cannyOut, otsu, otsu * 1 / 2, 3, 1);
// Find contours
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
findContours(cannyOut, contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));
// Get the moments
vector<Moments> mu(contours.size());
for (int i = 0; i < contours.size(); i++)
{
mu[i] = moments(contours[i], false);
}
// Get the mass centers:
vector<Point2f> mc(contours.size());
for (int i = 0; i < contours.size(); i++)
{
mc[i] = Point2f(mu[i].m10 / mu[i].m00, mu[i].m01 / mu[i].m00);
}
// Draw contours
Mat drawing = Mat::zeros(cannyOut.size(), CV_8UC3);
string sObjectNumber; // string which will contain the result
ostringstream sContourNumber; // stream used for the conversion
for (int i = 0; i< contours.size(); i++)
{
// drawing.setTo(Scalar(0.0,0.0,0.0));
sContourNumber << i;
sObjectNumber = sContourNumber.str(); // Convert int to string
Point pCoordinates(mc[i].x + 3, mc[i].y - 3); // Text's coordinates (A little bit off from mass center)
Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
drawContours(drawing, contours, i, color, 2, 8, hierarchy, 0, Point());
circle(drawing, mc[i], 4, color, -1, 8, 0); // Draw mass center
putText(drawing, sObjectNumber, pCoordinates, CV_FONT_HERSHEY_COMPLEX, 1, color, 2, 8); // Write object number
sContourNumber.str(""); // Clear string
sContourNumber.clear(); // Clear any error flags
// imshow("Contours", drawing);
// waitKey();
}
double hu[7];
for (int i = 0; i < contours.size(); i++)
{
cout << "Contour: " << i << " Area: " << contourArea(contours[i]) << " Length: " << arcLength(contours[i], true) << "\n";
for (int j = 0; j < 7; j++)
{
HuMoments(mu[i], hu);
cout << "Contour: " << i << " Hu: " << j << " Result: " << hu[j] << "\n";
}
cout << "\n";
}
imshow("Contours", drawing);
waitKey(0);
return(0);
}
Very thanks for all!
Diego
Because this is a project for an image processing class, I have to implement a couple of linear filters from scratch( I'm not supposed to use already implemented features of OpenCV like Sobel, not even the 2D filter function). The code is at the end of the question.
Since images processed with the Sobel operator give similar results with the Prewitt ones, I used as a test a window where I display a Sobel-processed image.
I only got to the point where I applied an operator on the horizontal direction, but I'm already getting weird results. Images speak for themselves:
Original image:
Original image
My result using the Prewitt operator on the horizontal direction:
My processed image
I get a weird blue-beige pattern instead of a black-and-white horizontal lines. What is happening?
Here is the code:
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/opencv.hpp"
#include <stdlib.h>
#include <stdio.h>
using namespace cv;
using namespace std;
int main(int, char** argv)
{
int Hprewitt[3][3] = { { -1, 0, 1 }, { -1, 0, 1 }, { -1, 0, 1 } };
int Vprewitt[3][3] = { { -1, -1, -1 }, { 0, 0, 0 }, { 1, 1, 1 } };
int tempInput[3][3];
int tempPixel=0;
Mat src, src_gray;
Mat grad;
const char* window_name = "Sobel Edge Detector";
const char* window_name2 = "Prewitt";
int scale = 1;
int delta = 0;
int ddepth = CV_16S;
int computedIntensity;
src = imread(argv[1]);
if (src.empty())
{
return -1;
}
namedWindow(window_name2, WINDOW_AUTOSIZE);
Mat HprewittMat(src.rows, src.cols, CV_8UC3, Scalar(0, 0, 0));
GaussianBlur(src, src, Size(3, 3), 0, 0, BORDER_DEFAULT);
cvtColor(src, src_gray, COLOR_RGB2GRAY);
namedWindow(window_name, WINDOW_AUTOSIZE);
Scalar intensity = src.at<uchar>(Point(50, 50)); // this is how to access intensity at a certain pixel
Vec3b scalarTempPixel = src.at<Vec3b>(Point(1, 1));
cout << "Pixel (50,50) has intensity: " << intensity.val[0] << endl;
// applying horizontal prewitt operator
cout << "\n Image has resolution: " << src.cols << "x" << src.rows << "\n";
for (int i = 2; i < src.cols-1; i++){ // currently going from column 2 to n-2, same for row
for (int j = 2; j < src.rows-1; j++){
// storing a temporary 3x3 input matrix centered on the current pixel
// cout << "Matrix centered on pixel: [" << i << "," << j << "] \n";
for (int k = -1; k < 2; k++){
for (int l = -1; l < 2; l++){
intensity = src.at<uchar>(Point(i + k, j + l));
tempInput[k+1][l+1] = intensity.val[0];
// cout << "[" << intensity.val[0] << "]";
}
// cout << " \n";
}
// convolution of horizontal prewitt kernel with current 3x3 matrix
for (int x = 0; x < 3; x++){
for (int y = 0; y < 3; y++){
tempPixel = tempPixel + tempInput[x][y] * Hprewitt[x][y];
}
}
scalarTempPixel[0] = tempPixel;
HprewittMat.at<Vec3b>(Point(i, j)) = scalarTempPixel;
}
}
Mat grad_x, grad_y;
Mat abs_grad_x, abs_grad_y;
Sobel(src_gray, grad_x, ddepth, 1, 0, 3, scale, delta, BORDER_DEFAULT);
convertScaleAbs(grad_x, abs_grad_x);
Sobel(src_gray, grad_y, ddepth, 0, 1, 3, scale, delta, BORDER_DEFAULT);
convertScaleAbs(grad_y, abs_grad_y);
addWeighted(abs_grad_x, 0.5, abs_grad_y, 0.5, 0, grad);
imshow(window_name, grad);
imshow(window_name2, HprewittMat);
waitKey(0);
return 0;
}
So at this point I'm doing the following:
I'm reading an image in "src", then I create the HprewittMat which I initialize it with the number of rows and cols of the original image, but with black pixels. I then convert the src image to a gray one. Then I iterate through each pixel of the original image, and for each pixel I'm doing a convolution mask with the the surrounding pixels and the horizontal prewitt kernel. Then I store that value in "tempPixel" and put it in the HprewittMat image.
The next step would be to do the same but with the vertical kernel, and then calculate the gradient kernel.
I'm asking this question because I've found similar questions on how to manipulate individual pixels but usually for python or java. This might also be some flaw in the logic I'm using.
I am using chamfer matching to match a template with a reference image. I am using OpenCV'r chamermatching() method. I get the matching scores, but how can I get the correspondences ? In other words, corresponding to each cost, how can I get the template point to reference image point correspondence ? Thanks in advance!
I am using the following code:
int main( int argc, const char** argv )
{
Mat img = imread(argv[1], 0);
Mat tpl = imread(argv[2], 0);
GaussianBlur(img, img, cv::Size(3, 3), 4.0);
GaussianBlur(tpl, tpl, cv::Size(3, 3), 4.0);
imshow("Image", img);
imshow("Template", tpl);
if (img.empty() || tpl.empty())
{
cout << "Could not read image files";
return -1;
}
Mat cimg;
cvtColor(img, cimg, COLOR_GRAY2BGR);
// if the image and the template are not edge maps but normal grayscale images,
// you might want to uncomment the lines below to produce the maps. You can also
// run Sobel instead of Canny.
// Canny(img, img, 5, 50, 3);
// Canny(tpl, tpl, 5, 50, 3);
vector<vector<Point> > results;
vector<float> costs;
int best = chamerMatching( img, tpl, results, costs );
if( best < 0 )
{
cout << "matching not found" << endl;
return -1;
}
cout << results.size() << endl;
size_t i, n = results[best].size();
for( i = 0; i < n; i++ )
{
Point pt = results[best][i];
if( pt.inside(Rect(0, 0, cimg.cols, cimg.rows)) )
cimg.at<Vec3b>(pt) = Vec3b(0, 255, 0);
}
imshow("result", cimg);
float total_cost = 0.0;
for(int i=0;i<costs.size();i++)
total_cost += costs[i];
cout << total_cost << "\n";
waitKey();
return 0;
}
I'm using Opencv2.4.6 and Netbeans IDE for C++.
I'm trying to do a program to detect a face with the CascadeClassifier, and then pass the Rect of the face to the Camshift function to track this face.
To do that, I took the sample code "Camshiftdemo.cpp" that comes in the samples folder of opencv and I've modified. In my code instead of use the mouse to select the region over which you want to do tracking, is the cascade classifier which passes that information.
#include "opencv2/video/tracking.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/objdetect/objdetect.hpp"
#include <iostream>
#include <ctype.h>
using namespace cv;
using namespace std;
Mat image;
int trackObject = 0;
Rect selection;
int main()
{
VideoCapture cap;
Rect trackWindow;
int hsize = 16;
float hranges[] = {0,180};
const float* phranges = hranges;
int matchesNum = 0;
CascadeClassifier cascade;
if (!cascade.load("C:/opencv/data/haarcascades/haarcascade_frontalface_default.xml")) {
cout << "Cannot load face xml!" << endl;
return -1;
}
cap.open("D:/Videos_Proy/ProgramacionII/CAMERA3_clase1.MP4");
if (!cap.isOpened()) {
cout << "***Could not initialize capturing...***\n";
return -1;
}
namedWindow( "Result", 1 );
Mat frame, hsv, hue, hist, mask, backproj;
for(;;)
{
cap >> frame;
if( frame.empty() )
break;
frame.copyTo(image);
if ( !trackObject )
{
Mat grayframe;
vector <Rect> facesBuf;
int detectionsNum = 0;
cvtColor(image, grayframe, CV_BGR2GRAY);
cascade.detectMultiScale(grayframe, facesBuf, 1.2, 4, CV_HAAR_FIND_BIGGEST_OBJECT |
CV_HAAR_SCALE_IMAGE, cvSize(0, 0));
detectionsNum = (int) facesBuf.size();
Rect *faceRects = &facesBuf[0];
//It must found faces in three consecutives frames to start the tracking to discard false positives
if (detectionsNum > 0)
matchesNum += 1;
else matchesNum = 0;
if ( matchesNum == 3 )
{
trackObject = -1;
selection = faceRects[0];
}
for (int i = 0; i < detectionsNum; i++)
{
Rect r = faceRects[i];
rectangle(image, Point(r.x, r.y), Point(r.x + r.width, r.y + r.height), CV_RGB(0, 255, 0));
}
}
if( trackObject )
{
cvtColor(image, hsv, CV_BGR2HSV);
inRange(hsv, Scalar(0, 69, 53),
Scalar(180, 256, 256), mask);
int ch[] = {0, 0};
hue.create(hsv.size(), hsv.depth());
mixChannels(&hsv, 1, &hue, 1, ch, 1);
if( trackObject < 0 )
{
Mat roi(hue, selection), maskroi(mask, selection);
calcHist(&roi, 1, 0, maskroi, hist, 1, &hsize, &phranges);
normalize(hist, hist, 0, 255, CV_MINMAX);
trackWindow = selection;
trackObject = 1;
}
calcBackProject(&hue, 1, 0, hist, backproj, &phranges);
backproj &= mask;
RotatedRect trackBox = CamShift(backproj, trackWindow,
TermCriteria( CV_TERMCRIT_EPS | CV_TERMCRIT_ITER, 10, 1 ));
if( trackWindow.area() <= 1 )
{
int cols = backproj.cols, rows = backproj.rows, r = (MIN(cols, rows) + 5)/6;
trackWindow = Rect(trackWindow.x - r, trackWindow.y - r,
trackWindow.x + r, trackWindow.y + r) &
Rect(0, 0, cols, rows);
}
ellipse( image, trackBox, Scalar(0,0,255), 3, CV_AA );
}
imshow( "Result", image );
if(waitKey(30) >= 0) break;
}
return 0;
}
This code makes sense to me, and when I Build it in Netbeans do not get any error, the problem is that don't run and Netbeans don't give any clue, only says: RUN FAILED (exit value -1.073.741.819, total time: 5s)
Anyone could help me and give any idea about what is happening. Thanks!!