I have an image i1. I am supposed to create another Mat m1 of size (image.rows*3, image.cols*3).
In m1, I'm supposed to fill the pixel value in the following way. (Please do see the image):
Here is my code-
#include <highgui.h>
#include "opencv2/opencv.hpp"
#include <fstream>
using namespace cv;
static Mat NeurMap1, NeurMap2, NeurMap3, frame, hsv_Frame;
std::ofstream myfile;
void InitializeNeurMap(cv::Mat Channel[3])
{
int i=0,j=0,m_i=0,m_j=0, t1=0, t2=0;
for(i=0; i < frame.rows; i++)
{
for(j=0;j < frame.cols;j++)
{
t1= i*n+1; t2 = j*n+1;
for(m_i=t1-1; m_i <= t1+1;m_i++)
{
for(m_j=t2-1; m_j <= t2+1; m_j++)
{
NeurMap1.at<uchar>(m_i, m_j)= frame.at<uchar>(i,j);
}
}
}
}
std::cout<<m_j;
myfile<<frame;
}
int main()
{
myfile.open("NeurMaptext.txt");
String filename="BootStrap/b%05d.bmp";// sequence of frames are read
VideoCapture cap(filename);
if(!cap.isOpened()) // check if we succeeded
return -1;
namedWindow("edges",1);
//namedWindow("frames",1);
Mat Channel[3];
cap>>frame;
NeurMap1 = Mat::zeros(frame.rows*n, frame.cols*n, frame.type());
InitializeNeurMap(Channel);
imshow("edges",NeurMap1);waitKey(33);
for(;;)
{
cap>>frame;
if(frame.empty())
break;
}
system("pause");
return 0;
}
The input image is RGB[160*120]. Why am I not getting the columns in the output image given in the link above?.
You can simply call resize() by passing the INTER_NEAREST parameter, i.e. using the nearest-neighbor interpolation.
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;
int main()
{
unsigned char data[] = { 1, 2, 3, 4, 5, 6 };
Mat img(2, 3, CV_8UC1, data);
cout << img << endl;
Mat res(6, 9, CV_8UC1);
resize(img, res, res.size(), 0, 0, INTER_NEAREST);
cout << res << endl;
return 0;
}
You will get:
In you are getting three only one-third of image filled because, probably you are passing 3 channel(colour) image to the function and treat it as a single channel image. So change the above code to,
void InitializeNeurMap(cv::Mat Channel[3])
{
for(int i=0; i < frame.rows; i++){
for(int j=0;j < frame.cols;j++){
for(int k=0;k<n;k++){
for(int l=0;l<n;l++){
NeurMap1.at<Vec3b>(i*n+k,j*n+l)[0] = frame.at<Vec3b>(i,j)[0]; //Access Blue channel
NeurMap1.at<Vec3b>(i*n+k,j*n+l)[1] = frame.at<Vec3b>(i,j)[1];//Access green channel
NeurMap1.at<Vec3b>(i*n+k,j*n+l)[2] = frame.at<Vec3b>(i,j)[2]; //Access red channel
}
}
}
}
myfile<<frame;
}
See the reult
Related
I've been reading about opencv and I've been doing some exercises, in this case I want to perform an image equalization, I have implemented the following code, but when I execute it I get the following error:
"Segmentation fault (core dumped)"
So I have no idea what is due.
The formula I am trying to use is the following:
equalization
The code is the following:
#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <stdio.h>
using namespace cv;
using namespace std;
void equalization(cv::Mat &image,cv::Mat &green, int m) {
Mat eqIm;
int nl= image.rows; // number of lines
int nc= image.cols * image.channels();
for (int j=0; j<nl; j++) {
uchar* data= image.ptr<uchar>(j);
uchar* data2= green.ptr<uchar>(j);
uchar* eqIm= green.ptr<uchar>(j);
for (int i=0; i<nc; i++) {
eqIm[i]= data[i]+m-data2[i];
}
}
cv::imshow("Image",eqIm);
imwrite("eqIm.png",eqIm);
}
float mean(cv::Mat &image){
cv:Scalar tempVal = mean( image );
float myMAtMean = tempVal.val[0];
cout << "The value is " << myMAtMean;
}
int main(int argc, char** argv ){
Mat dst;
Mat image= cv::imread("img.jpg");
Mat green= cv::imread("green.jpg");
cv::imshow("Image",image);
float m= mean(image);
equalization(image,green,m);
cv::namedWindow("Image");
cv::imshow("Image",image);
imwrite("equalizated.png",dst);
waitKey(0);
return 0;
}
and the image "Equalization.png" that is written contains nothing
You never initialized Mat eqIm, so when you do cv::imshow("Image", eqIm);
imwrite("eqIm.png", eqIm); there is nothing in the mat. https://docs.opencv.org/2.4/doc/tutorials/core/mat_the_basic_image_container/mat_the_basic_image_container.html
Also, I should note that you have 2 variables of eqIm. That may be part of the confusion.
One last thing, in your mean function, you may end up with a recursive function. You should specify what mean function you are using in the mean function you create, i.e.
float mean(cv::Mat &image) {
cv:Scalar tempVal = cv::mean(image);
float myMAtMean = tempVal.val[0];
cout << "The value is " << myMAtMean;
return myMAtMean;
}
The following is something closer to what you are looking for in your equalization function.
void equalization(cv::Mat &image, cv::Mat &green, int m) {
Mat eqIm(image.rows,image.cols,image.type());
int nl = image.rows; // number of lines
int nc = image.cols * image.channels();
for (int j = 0; j<nl; j++) {// j is each row
for (int ec = 0; ec < nc; ec++) {//ec is each col and channels
eqIm.data[j*image.cols*image.channels() + ec] = image.data[j*image.cols*image.channels() + ec] + m - green.data[j*image.cols*image.channels() + ec];
}
}
cv::imshow("Image", eqIm);
imwrite("eqIm.png", eqIm);
}
I do j*image.cols*image.channels() to step through the entire size of j lines (the number of columns times the number of channels per pixel).
I've written a code to create bounding boxes and draw the Farneback optical flow inside. The optical flow is calculated normally before hand and then it is drawn separately for each ROI box.
The problem comes when I draw the flow. The flow comes out looking normal, but shifted down and right. Here's the output, notice the bottom right has the flow of the moving person.
Here is the frame with the flow drawn everywhere, showing where the flow should be drawn.
The code attached is stripped down for simplicity, so excuse me if there are a few undeclared Matrices or something.
#include ...
using namespace cv;
using namespace std;
Mat currentImage, img, printr, gray ,prevgray, flow;
void getRectanglesandROI(Mat &Mask, Mat &imgTmp, Mat &imgOut, vector<Rect> &outBoxes);
void DrawFlowMap(Mat Image, Mat ROI, Rect Box, Point centre);
int main (int argc, char *argv[]) {
VideoCapture inVid("input.avi");
if (!inVid.isOpened()) {
cout << "Failed to open the input video" << endl;
exit(5);}
int loop=0, count =0, MaxTargets=0;
bool test=true;
namedWindow("Detected");
int ex = inVid.get(CV_CAP_PROP_FOURCC);
double fps = inVid.get(CV_CAP_PROP_FPS);
int wait=1000/fps;
Size S = Size( (int) inVid.get(CV_CAP_PROP_FRAME_WIDTH), (int) inVid.get(CV_CAP_PROP_FRAME_HEIGHT));
int fr =inVid.get(CV_CAP_PROP_FRAME_COUNT);
VideoWriter output; // Open the output
output.open("output.avi", ex, fps, S, true);
if (!output.isOpened())
{
cout << "Could not open the output video for write: " << endl;
return -1;
}
//=============4EVR=================
while(test){
inVid>>currentImage;
if (currentImage.empty())
{
count++;
//if (count==1){if (waitKey(0)==27){waitKey(2);}}
if (count==1){fs.release(); break;}
cout <<"Max Targets=" <<MaxTargets<< endl<< "End of video, looping" << endl<<endl;
inVid.set(CV_CAP_PROP_POS_AVI_RATIO, 0);
loop=0;
}
cvtColor(currentImage, gray,CV_RGB2GRAY);
if (prevgray.empty()){gray.copyTo(prevgray);}
currentImage.copyTo(img);
calcOpticalFlowFarneback(prevgray,gray,flow,0.5,3,21,20,5,1.2,0);
vector<Rect> outputBoxes;
getRectanglesandROI(fgMaskMOG2, img, currentImage, outputBoxes);
gray.copyTo(prevgray);
imshow("Detected", currentImage);
waitKey(wait);
}
return 0;
}
//============END===========================================================
void getRectanglesandROI(Mat &Mask, Mat &imgTmp, Mat &imgOut, vector<Rect> &outBoxes){
vector<vector<Point> > v;
vector<int> targets;
int tarArea=1;
findContours(Mask, v, CV_RETR_EXTERNAL/*CV_RETR_LIST*/, CV_CHAIN_APPROX_SIMPLE);
for (int j = 0; j < v.size(); j++) {
if (tarArea < v[j].size()) { // excluding tiny contours
targets.push_back(j);
}
}
for (int j = 0; j < targets.size(); j++) {
drawContours(imgTmp, v, targets[j], Scalar(255, 0, 255), 1, 8);
Rect rect = boundingRect(v[targets[j]]);
roi=currentImage(rect);
DrawFlowMap(currentImage, roi, rect);
}
}
void DrawFlowMap(Mat Image, Mat ROI, Rect Box){
Point pt1 = Point(Box.x, Box.y);
for( int y=0; y<roi.rows; y+=5){ //this is the issue area, probably.
for (int x=0;x<roi.cols;x+=5){
const Point2f& flowatxy=flow.at<Point2f>(y,x);
line(Image, Point(cvRound(pt1.x+x), cvRound(pt1.y+y)),
Point(cvRound(pt1.x+x+flowatxy.x), cvRound(pt1.y+y+flowatxy.y)), Scalar(0,255,0)); ///FLOW LINES
}
}
}
Easy peasy, after looking at the images for a while (crying) I noticed that it was drawing the flow in the right places, but the flowatxy in that place was wrong. So I changed the flowatxy declaration to the following:
const Point2f& flowatxy=flow.at<Point2f>( pt1.y+y , pt1.x+x );
Before going into deep of my question, I want you to know that I've read other posts on this forum, but none regards my problem.
In particular, the post here answers the question "how to do this?" with k-means, while I already know that I have to use it and I'd like to know why my implementation doesn't work.
I want to use k-means algorithm to divide pixels of an input image into clusters, according to their color. Then, after completing such task, I want each pixel to have the color of the center of the cluster it's been assigned to.
Taking as reference the OpenCV examples and other stuff retrieved on the web, I've designed the following code:
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <iostream>
using namespace std;
using namespace cv;
int main( int argc, char** argv )
{
Mat src = imread( argv[1], 1 );
// reshape matrix
Mat resized(src.rows*src.cols, 3, CV_8U);
int row_counter = 0;
for(int i = 0; i<src.rows; i++)
{
for(int j = 0; j<src.cols; j++)
{
Vec3b channels = src.at<Vec3b>(i,j);
resized.at<char>(row_counter,0) = channels(0);
resized.at<char>(row_counter,1) = channels(1);
resized.at<char>(row_counter,2) = channels(2);
row_counter++;
}
}
//cout << src << endl;
// change data type
resized.convertTo(resized, CV_32F);
// determine termination criteria and number of clusters
TermCriteria criteria(TermCriteria::COUNT + TermCriteria::EPS, 10, 1.0);
int K = 8;
// apply k-means
Mat labels, centers;
double compactness = kmeans(resized, K, labels, criteria, 10, KMEANS_RANDOM_CENTERS, centers);
// change data type in centers
centers.convertTo(centers, CV_8U);
// create output matrix
Mat result = Mat::zeros(src.rows, src.cols, CV_8UC3);
row_counter = 0;
int matrix_row_counter = 0;
while(row_counter < result.rows)
{
for(int z = 0; z<result.cols; z++)
{
int index = labels.at<char>(row_counter+z, 0);
//cout << index << endl;
Vec3b center_channels(centers.at<char>(index,0),centers.at<char>(index,1), centers.at<char>(index,2));
result.at<Vec3b>(matrix_row_counter, z) = center_channels;
}
row_counter += result.cols;
matrix_row_counter++;
}
cout << "Labels " << labels.rows << " " << labels.cols << endl;
//cvtColor( src, gray, CV_BGR2GRAY );
//gray.convertTo(gray, CV_32F);
imshow("Result", result);
waitKey(0);
return 0;
}
Anyway, at the end of computation, I simply get a black image.
Do you know why?
Strangely, if I initialize result matrix as
Mat result(src.size(), src.type())
at the end of algorithm it will display exactly the input image, without any segmentation.
In particular, I have two doubts:
1) is it correct to lay the RGB values of a pixel on each row of matrix resized the way I've done it? is there a way to do it without a loop?
2) what's exactly the content of centers, after k-means function finishes working? it's a 3 columns matrix, does it contains the RGB values of clusters' centers?
thanks for support.
-The below posted OpenCV program assigns the user preferred color to a particular pixel value in an image
-ScanImageAndReduceC() is a predefined method in OpenCV to scan through all the pixels of an Image
-I.atuchar>(10, 10) = 255; is used to access a particular pixel value of an image
Here is the code:
Mat& ScanImageAndReduceC(Mat& I)
{
// accept only char type matrices
CV_Assert(I.depth() == CV_8U);
int channels = I.channels();
int nRows = I.rows;
int nCols = I.cols * channels;
if (I.isContinuous())
{
nCols *= nRows;
nRows = 1;
}
int i, j;
uchar* p;
for (i = 0; i < nRows; ++i)
{
p = I.ptr<uchar>(i);
for (j = 0; j < nCols; ++j)
{
I.at<uchar>(10, 10) = 255;
}
}
return I;
}
-------Main Program-------
Calling the above method in our main program
diff = ScanImageAndReduceC(diff);
namedWindow("Difference", WINDOW_AUTOSIZE);// Create a window for display.
imshow("Difference", diff); // Show our image inside it.
waitKey(0); // Wait for a keystroke in the window
return 0;
}
I want to equate the 0 pixel value to the pixel location having 0 pixel value in Mask image to the same location in the grayimg12 image, which is a gray image. When I put the for loop in try-catch block it is giving me error and assertion failed, without using try-catch the error is "Unhandled Exception at 0x755b0f22 and cv:: Exception at memory location 0x004af338.. I am using opencv 3.0.0 beta version and Visual Studio 2010.
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/calib3d.hpp>
#include <iostream>
#include <sstream>
using namespace cv;
using namespace std;
int main()
{
// Reading Mask and Creating New Image
Mat grayimg, grayimg12, input, Mask; int keyboard;
input = imread("peter.jpg");
cvtColor(input, grayimg, COLOR_BGR2GRAY);
grayimg.copyTo(grayimg12, grayimg);
namedWindow("Gray Converted Frame");
imshow("Gray Converted Frame", grayimg);
int r = input.rows; int c = input.cols;
Mask = grayimg > 100;
namedWindow("Binary Image");
imshow("Binary Image", Mask);
try
{
for (int i=1;i<=r;i++)
{
for (int j=1;j<=c; j++)
{
if (Mask.at<uchar>(i,j) == 0)
{
grayimg12.at<uchar>(i,j) = 0;
}
else
grayimg12.at<uchar>(i,j) = grayimg.at<uchar>(i,j);
}
}
}
catch(Exception)
{
cout<<"Hi..";
}
namedWindow("Gray Output Image");
imshow("Gray Output Image", grayimg12);
keyboard = waitKey( 10000 );
return 0;
}
Your loop indices are off by one, so you get an exception when you try to access memory beyond the image bounds. Change:
for (int i=1;i<=r;i++)
{
for (int j=1;j<=c; j++)
{
to:
for (int i=0;i<r;i++) // for i = 0 to r-1
{
for (int j=0;j<c; j++) // for j = 0 to c-1
{
Note that in C, C++ and related languages, arrays are zero-based. So the valid index range for an array of size N is from 0 to N-1 inclusive.
Here is my code, which uses OpenCV 2.4.5
Histogram1D.h
#ifndef HISTOGRAM1D_H
#define HISTOGRAM1D_H
#include <iostream>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
using namespace std;
using namespace cv;
class Histogram1D
{
public:
Histogram1D();
//Histogram generators
MatND getHistogram(Mat );
Mat getHistogramImage(Mat );
//Generate Negative Image
Mat applyLookup(Mat ,Mat );
//Generate improved image with equalized histogram
Mat equalize(Mat image);
private:
int histSize[1];//Number of bins
float hRanges[2];//Max and Min pixel values
const float *ranges[1];
int channels[1];//Only one channel will be used
};
#endif // HISTOGRAM1D_H
Histogram1D.cpp
#include "Histogram1D.h"
Histogram1D::Histogram1D()
{
histSize[0] = 256;
hRanges[0] = 0.0;
hRanges[1] = 255.0;
ranges[0] = hRanges;
channels[0] = 0;
}
MatND Histogram1D::getHistogram(Mat image)
{
MatND hist;
cv::calcHist(&image,1,channels,Mat(),hist,1,histSize,ranges);
return hist;
}
Mat Histogram1D::getHistogramImage(Mat image)
{
MatND histo = getHistogram(image);
//Get minimum and maximum value bins
double minVal = 0;
double maxVal = 0;
minMaxLoc(histo,&minVal,&maxVal,0,0);
//Image on which to display histogram
Mat histImage(histSize[0],histSize[0],CV_8U,Scalar(255));
//Set highest point at 90% of nbins
int hpt = static_cast<int>(0.9,histSize[0]);
//Draw a vertical line for each bin
for(int i=0;i<histSize[0];i++)
{
float binVal = histo.at<float>(i);
int intensity = static_cast<int>(binVal*hpt/maxVal);
line(histImage,Point(i,histSize[0]),Point(i,histSize[0]-intensity),Scalar::all(0));
}
return histImage;
}
Mat Histogram1D::applyLookup(Mat image,Mat lookup)
{
Mat result;
cv::LUT(image,lookup,result);
return result;
}
Mat Histogram1D::equalize(Mat image)
{
Mat result;
cv::equalizeHist(image,result);
return result;
}
HistogramMain.cpp
#include "Histogram1D.h"
int main()
{
Histogram1D h;
Mat image = imread("C:/Users/Public/Pictures/Sample Pictures/Penguins.jpg",CV_LOAD_IMAGE_GRAYSCALE);
cout << "Number of Channels: " << image.channels() << endl;
namedWindow("Image");
imshow("Image",image);
Mat histogramImage = h.getHistogramImage(image);
namedWindow("Histogram");
imshow("Histogram",histogramImage);
Mat thresholded;
threshold(image,thresholded,60,255,THRESH_BINARY);
namedWindow("Binary Image");
imshow("Binary Image",thresholded);
Mat negativeImage;
int dim(256);
negativeImage = h.applyLookup(image,Mat(1,&dim,CV_8U));
namedWindow("Negative Image");
imshow("Negative Image",negativeImage);
Mat equalizedImage;
equalizedImage = h.equalize(image);
namedWindow("Equalized Image");
imshow("Equalized Image",equalizedImage);
waitKey(0);
return 0;
}
When you run this code, the negative image is 100% black! The most amazing this is, if you remove all other code from HistogramMain.cpp but keep the code below which is related to negative image, you will get the correct negative image! Why is this?
I am using QT latest version which use the VS 2010 Compiler.
Mat negativeImage;
int dim(256);
negativeImage = h.applyLookup(image,Mat(1,&dim,CV_8U));
namedWindow("Negative Image");
imshow("Negative Image",negativeImage);
Your primary difficulty is that the expression Mat(1,&dim,CV_8U) allocates memory for a cv::Mat, but does not initialize any values. It is possible that your environment may fill uninitialized memory with zeros, which would explain the black image after calling applyLookup(). In any case, you should initialize the values in your lookup table in order to achieve correct results. For inverting the image, it is easy:
int dim(256);
cv::Mat tab(1,&dim,CV_8U);
uchar* ptr = tab.ptr();
for (size_t i = 0; i < tab.total(); ++i)
{
ptr[i] = 255 - i;
}
There are a few other issues with your code:
The line
int hpt = static_cast<int>(0.9,histSize[0]);
should be
int hpt = static_cast<int>(0.9*histSize[0]);
to do what your comment indicates. Pay attention to your compiler warnings!
You also have problems with your histogram ranges.
By the way, with opencv2 image are now numpy array, so to negative a grey 8-bits image in python, it's simply:
img = 255 - img