Im using a Basler camera, and I'm trying to save the grabbed image with OpenCV. However, when i try to use imwrite(), I get this error:
imwrite_('C:/Users/Uporabnik/Desktop/slika.png'): can't write data: unknown exception
My conversion of the grabbed image:
openCvImage = Mat(image.GetHeight(), image.GetWidth(), CV_16U, (uint8_t *)image.GetBuffer());
Trying to save the image:
cv::imwrite("C:/Users/Uporabnik/Desktop/slika.png", openCvImage);
I am also using basler camera. You also need to share codes which includes basler configurations.Here is how I used basler camera to get frame in the format of opencv:
#include <pylon/usb/BaslerUsbInstantCamera.h>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <pylon/PylonIncludes.h>
using namespace std;
using namespace cv;
using namespace Pylon;
using namespace GenApi;
using namespace Basler_UsbCameraParams;
int main()
{
Mat openCvImage;
Pylon::PylonAutoInitTerm autoInitTerm;
CBaslerUsbInstantCamera camera(CTlFactory::GetInstance().CreateFirstDevice());
CImageFormatConverter formatConverter;
CPylonImage pylonImage;
camera.MaxNumBuffer = 1;
formatConverter.OutputPixelFormat= PixelType_BGR8packed;
camera.StartGrabbing( c_countOfImagesToGrab);
const uint8_t *pImageBuffer = (uint8_t *) ptrGrabResult->GetBuffer();
formatConverter.Convert(pylonImage, ptrGrabResult);
openCvImage= cv::Mat(ptrGrabResult->GetHeight(), ptrGrabResult>GetWidth(), CV_8UC3, (uint8_t *) pylonImage.GetBuffer());
imshow("Basler Frame",openCvImage);
waitKey(0);
return 0;
}
But first of all you need to use "imshow" function to see image.
If you can, the problem is in your directory part. Otherwise you need to share code about initiating basler camera.
Please just pay attention to the dimension of your image, you can simply print and see if the shape is correct. In my case, I include the batchsize dimension to the image shape by mistake, and I solve it by image = image[0].
Related
I have 400x400 photo. I took the pieces as 4 separate photos of 100 * 400 and recorded them as 1, 2, 3, 4.jpg.
I have to combine 4 images croped from the one photo and get the original photo of 400 * 400. How can I do it ?
I don't want to use a ready(set) function. I need to do with for loop.
This is not going to be easy. Just reading a JPG without using a library could take weeks or months for a professional.
You should use a library. I would recommend CImg from here as a good starting point.
Failing that, I would suggest using ImageMagick to convert your JPGs to NetPBM PPM format then you can read them much more easily.
magick 1.jpg -depth 8 1.ppm
When you have written the code to combine them, you can convert the combined PPM file back into a JPG with:
magick combined.ppm combined.jpg
If you don't want to use available functions, you can create a 400x400 mask and assign the pixel values of each piece to the mask.
Here is the code:
#include <opencv2/highgui.hpp>
#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include <iostream>
using namespace cv;
using namespace std;
int main() {
// 4 Pieces
Mat piece_1 = imread("/ur/image/directory/1.jpg",CV_LOAD_IMAGE_GRAYSCALE);
Mat piece_2 = imread("/ur/image/directory/2.jpg",CV_LOAD_IMAGE_GRAYSCALE);
Mat piece_3 = imread("/ur/image/directory/3.jpg",CV_LOAD_IMAGE_GRAYSCALE);
Mat piece_4 = imread("/ur/image/directory/4.jpg",CV_LOAD_IMAGE_GRAYSCALE);
// Mask
Mat source_image = Mat::zeros(Size(400,400),CV_8UC1);
for(int i=0;i<source_image.rows;i++)
{
for(int j=0;j<source_image.cols;j++)
{
if(i<=99)
source_image.at<uchar>(i,j)=piece_1.at<uchar>(i,j);
if(i>99 && i<=199)
source_image.at<uchar>(i,j)=piece_2.at<uchar>(i-100,j);
if(i>199 && i<=299)
source_image.at<uchar>(i,j)=piece_3.at<uchar>(i-200,j);
if(i>299 && i<=399)
source_image.at<uchar>(i,j)=piece_4.at<uchar>(i-300,j);
}
}
imshow("Result",source_image);
waitKey(0);
return 0;
}
I have seen some algorithms on how to remove a shadow from an image using OpenCV with C++. I have looked around but haven't find the way to not just erase the shadow, but store it on a new image alone.
What I am doing with this code is to convert the original image (that I obtained from the Internet) to the HSV color space, change the value of V=180, which somehow removes the shadow, and then converting the image back to the BGR color space. I am clueless on how to 'extract' the removed shadow and save it to a different image...
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc.hpp>
using namespace cv;
using namespace std;
int main()
{
Mat srcImg;
Mat hsvImg;
Mat bgrImg;
srcImg = imread("pcb-2008.jpg");
cvtColor(srcImg, hsvImg, CV_BGR2HSV);
imwrite("1.hsv.jpg", hsvImg);
Mat channel[3];
split(hsvImg, channel);
channel[2] = Mat(hsvImg.rows, hsvImg.cols, CV_8UC1, 180);
merge(channel, 3, hsvImg);
imwrite("2.hsvNoShadow.jpg", hsvImg);
cvtColor(hsvImg, bgrImg, CV_HSV2BGR);
imwrite("3.backToBgr.jpg", bgrImg);
return 0;
}
Sample image of a PCB
I am having a bit of trouble in trying to get the opencv face detection to work in QT with my basler cam; I have tried many different approaches to get it to work, using many different sample codes online. I just can’t seem to get it to work at all; in addition the attempts I have made have lowered my frame rate.
The code I used to capture a video with the basler cam is working great, I’m just having trouble implementing the face detection part. I will paste the code I have so far for the camera and opencv below. The code does get me a few red boxes appearing now and then, but it isn’t stable. I am also getting this error
Failed to load OpenCL runtime
I’m not sure what I am doing wrong, also is there a way to implement the face detection without lowering the frame rate, as it is already slow
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <opencv2/opencv.hpp>
#include <pylon/PylonIncludes.h>
//#include <pylon/PylonGUI.h>
//#ifdef PYLON_WIN_BUILD
//#include <pylon/PylonGUI.h>
//#endif
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/core/core.hpp"
#include <stdio.h>
#include <opencv2/opencv.hpp>
#include <iostream>
#include<time.h>
#include<stdlib.h>
using namespace cv;
// Namespace for using pylon objects.
using namespace Pylon;
// Namespace for using cout.
using namespace std;
static const uint32_t c_countOfImagesToGrab = 100;
cv::CascadeClassifier faceCade;
String faceCascadeName = "/usr/share/OpenCV/haarcascades/haarcascade_frontalface_alt.xml";
String FaceDetectWindow = "Face Detector Window";
String FaceDetectGrayWindow = "Face Detector Gray Window";
size_t i;
vector<Rect> faces;
cv::Mat camFrames, grayFrames;
int main()
{
// The exit code of the sample application.
int exitCode = 0;
// Automagically call PylonInitialize and PylonTerminate to ensure
// the pylon runtime system is initialized during the lifetime of this object.
Pylon::PylonAutoInitTerm autoInitTerm;
faceCade.load( faceCascadeName );
CGrabResultPtr ptrGrabResult;
namedWindow("CV_Image",WINDOW_AUTOSIZE);
CInstantCamera camera( CTlFactory::GetInstance().CreateFirstDevice());
cout << "Using device " << camera.GetDeviceInfo().GetModelName() << endl;
camera.Open();
GenApi::CIntegerPtr width(camera.GetNodeMap().GetNode("Width"));
GenApi::CIntegerPtr height(camera.GetNodeMap().GetNode("Height"));
Mat cv_img(width->GetValue(), height->GetValue(), CV_8UC3);
camera.StartGrabbing();
CPylonImage image;
CImageFormatConverter fc;
fc.OutputPixelFormat = PixelType_BGR8packed;
while(camera.IsGrabbing()){
camera.RetrieveResult( 5000, ptrGrabResult, TimeoutHandling_ThrowException);
if (ptrGrabResult->GrabSucceeded()){
fc.Convert(image, ptrGrabResult);
cv_img = cv::Mat(ptrGrabResult->GetHeight(), ptrGrabResult->GetWidth(), CV_8UC3,(uint8_t*)image.GetBuffer());
//cvtColor(cv_img, grayFrames, cv::COLOR_BGR2GRAY);
//equalizeHist(grayFrames, grayFrames);
faceCade.detectMultiScale(cv_img, faces, 1.1, 2, 0, Size(160, 160));
for (int i = 0; i < faces.size(); i++)
{
//Mat faceROI = grayFrames(faces[i]);
rectangle(cv_img, Rect(faces[i].x - 25,faces[i].y - 25,faces[i].width + 35 ,faces[i].height + 35), Scalar(0, 0, 255), 1, 1, 0);
Point center(faces[i].x + faces[i].width * 0.5,faces[i].y + faces[i].height * 0.5);
}
imshow("CV_Image",cv_img);
//imshow("FaceDetectGrayWindow", grayFrames);
waitKey(1);
if(waitKey(30)==27){
camera.StopGrabbing();
}
}
}
}
}
Thank you
i'm not quite sure about this but detectMultiScale function works with image in cv_8u type , and as i see you are using cv_8uc3, as i know cv_8u it's 8 bit pixel with 1 channel, cv_8uc3 it's alos 8 bit but 3 channels, you need to convert your image to gray scale , i saw you did that but you comment it?!!!
look at this link opencv_face_detection.
maybe that will fix your problem, and some people advice you to install opencl
sudo apt-get install ocl-icd-opencl-dev
I'm new to OpenCV.
I've given a link to the function imread as follows:
Mat logo = imread("http://files.kurento.org/img/mario-wings.png");
I've checked and the image exists on the given path. imread() still fails to read it.
Any mistake that I've made?
-Thanks
In fact imread is not able to read image data via http.
But it's possible using VideoCapture.
See this little snippet:
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
int main() {
cv::VideoCapture vc;
vc.open("http://files.kurento.org/img/mario-wings.png");
if(vc.isOpened() && vc.grab()) {
cv::Mat logo;
vc.retrieve(logo);
cv::namedWindow("t");
cv::imshow("t", logo);
cv::waitKey(0);
vc.release();
}
return 0;
}
I am now learning a code from the opencv codebook (OpenCV 2 Computer Vision Application Programming Cookbook): Chapter 5, Segmenting images using watersheds, page 131.
Here is my main code:
#include "opencv2/opencv.hpp"
#include <string>
using namespace cv;
using namespace std;
class WatershedSegmenter {
private:
cv::Mat markers;
public:
void setMarkers(const cv::Mat& markerImage){
markerImage.convertTo(markers, CV_32S);
}
cv::Mat process(const cv::Mat &image){
cv::watershed(image,markers);
return markers;
}
};
int main ()
{
cv::Mat image = cv::imread("/Users/yaozhongsong/Pictures/IMG_1648.JPG");
// Eliminate noise and smaller objects
cv::Mat fg;
cv::erode(binary,fg,cv::Mat(),cv::Point(-1,-1),6);
// Identify image pixels without objects
cv::Mat bg;
cv::dilate(binary,bg,cv::Mat(),cv::Point(-1,-1),6);
cv::threshold(bg,bg,1,128,cv::THRESH_BINARY_INV);
// Create markers image
cv::Mat markers(binary.size(),CV_8U,cv::Scalar(0));
markers= fg+bg;
// Create watershed segmentation object
WatershedSegmenter segmenter;
// Set markers and process
segmenter.setMarkers(markers);
segmenter.process(image);
imshow("a",image);
std::cout<<".";
cv::waitKey(0);
}
However, it doesn't work. How could I initialize a binary image? And how could I make this segmentation code work?
I am not very clear about this part of the book.
Thanks in advance!
There's a couple of things that should be mentioned about your code:
Watershed expects the input and the output image to have the same size;
You probably want to get rid of the const parameters in the methods;
Notice that the result of watershed is actually markers and not image as your code suggests; About that, you need to grab the return of process()!
This is your code, with the fixes above:
// Usage: ./app input.jpg
#include "opencv2/opencv.hpp"
#include <string>
using namespace cv;
using namespace std;
class WatershedSegmenter{
private:
cv::Mat markers;
public:
void setMarkers(cv::Mat& markerImage)
{
markerImage.convertTo(markers, CV_32S);
}
cv::Mat process(cv::Mat &image)
{
cv::watershed(image, markers);
markers.convertTo(markers,CV_8U);
return markers;
}
};
int main(int argc, char* argv[])
{
cv::Mat image = cv::imread(argv[1]);
cv::Mat binary;// = cv::imread(argv[2], 0);
cv::cvtColor(image, binary, CV_BGR2GRAY);
cv::threshold(binary, binary, 100, 255, THRESH_BINARY);
imshow("originalimage", image);
imshow("originalbinary", binary);
// Eliminate noise and smaller objects
cv::Mat fg;
cv::erode(binary,fg,cv::Mat(),cv::Point(-1,-1),2);
imshow("fg", fg);
// Identify image pixels without objects
cv::Mat bg;
cv::dilate(binary,bg,cv::Mat(),cv::Point(-1,-1),3);
cv::threshold(bg,bg,1, 128,cv::THRESH_BINARY_INV);
imshow("bg", bg);
// Create markers image
cv::Mat markers(binary.size(),CV_8U,cv::Scalar(0));
markers= fg+bg;
imshow("markers", markers);
// Create watershed segmentation object
WatershedSegmenter segmenter;
segmenter.setMarkers(markers);
cv::Mat result = segmenter.process(image);
result.convertTo(result,CV_8U);
imshow("final_result", result);
cv::waitKey(0);
return 0;
}
I took the liberty of using Abid's input image for testing and this is what I got:
Below is the simplified version of your code, and it works fine for me. Check it out :
#include "opencv2/objdetect/objdetect.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
using namespace cv;
using namespace std;
int main ()
{
Mat image = imread("sofwatershed.jpg");
Mat binary = imread("sofwsthresh.png",0);
// Eliminate noise and smaller objects
Mat fg;
erode(binary,fg,Mat(),Point(-1,-1),2);
// Identify image pixels without objects
Mat bg;
dilate(binary,bg,Mat(),Point(-1,-1),3);
threshold(bg,bg,1,128,THRESH_BINARY_INV);
// Create markers image
Mat markers(binary.size(),CV_8U,Scalar(0));
markers= fg+bg;
markers.convertTo(markers, CV_32S);
watershed(image,markers);
markers.convertTo(markers,CV_8U);
imshow("a",markers);
waitKey(0);
}
Below is my input image :
Below is my output image :
See the code explanation here : Simple watershed Sample in OpenCV
I had the same problem as you, following the exact same code sample of the cookbook (great book btw).
Just to place the matter I was coding under Visual Studio 2013 and OpenCV 2.4.8. After a lot of searching and no solutions I decided to change the IDE.
It's still Visual Studio BUT it's 2010!!!! And boom it works!
Becareful of how you configure Visual Studio with OpenCV. Here's a great tutorial for installation here
Good day to all