Corrupt JPEG data when doing Canny Edge Detection - c++

I'm using OpenCV to do Canny Edge Detection on images obtained by a camera over LAN.
This works, but I keep getting Corrupt JPEG data: premature end of data segment errors at run time once every few frames when I imshow("recv", canny), but I don't get that if I do imshow("recv", frame)
// Block until receive message from a client
do {
recvMsgSize = sock.recvFrom(buffer, BUF_LEN, sourceAddress, sourcePort);
} while (recvMsgSize > sizeof(int));
int total_pack = ((int*)buffer)[0];
char* longbuf = new char[double(PACK_SIZE * total_pack)];
for (int i = 0; i < total_pack; i++) {
recvMsgSize = sock.recvFrom(buffer, BUF_LEN, sourceAddress, sourcePort);
if (recvMsgSize != PACK_SIZE) {
continue;
}
memcpy(&longbuf[i * PACK_SIZE], buffer, PACK_SIZE);
}
Mat rawData = Mat(1, PACK_SIZE * total_pack, CV_8UC1, longbuf);
Mat frame = imdecode(rawData, IMREAD_COLOR);
if (frame.size().width == 0) {
continue;
}
Mat canny = CannyThreshold(frame);
imshow("recv", canny);
delete[] longbuf;

if you can get "frame" in mat form, then probably there is something wrong about this line:
Mat canny = CannyThreshold(frame);
Maybe you can change this line with something like this:
int minCannyThreshold = 190;
int maxCannyThreshold = 230;
Canny(frame, frame, minCannyThreshold, maxCannyThreshold, 5, true);
imshow("recv", frame);

Related

Forward process fail in ONNX model

I want to use FER+ Emotion Recognition in my project:
string modelPath = "../data/model.onnx";
Mat frame = imread("../data/Smile-Mood.jpg");
Mat gray;
cvtColor(frame, gray, COLOR_BGR2GRAY);
float scale = 1.0;
int inHeight = 64;
int inWidth = 64;
bool swapRB = false;
//Read and initialize network
cv::dnn::Net net = cv::dnn::readNetFromONNX(modelPath);
Mat blob;
//Create a 4D blob from a frame
cv::dnn::blobFromImage(gray, blob, scale, Size(inWidth, inHeight), swapRB, false);
//Set input blob
net.setInput(blob);
//Make forward pass
Mat prob = net.forward();
I have this error in last line:
Unhandled exception at 0x00007FFDA25AA799 in FERPlusDNNOpenCV.exe: Microsoft C++ exception: cv::Exception at memory location 0x00000063839BE050. occurred
OpenCV(4.1.0) Error: Assertion failed (ngroups > 0 && inpCn % ngroups == 0 && outCn % ngroups == 0) in cv::dnn::ConvolutionLayerImpl::getMemoryShapes
how to fix that?
UPDATE ACCORDING #Micka COMMENT:
Mat dstImg = Mat(64, 64, CV_32FC1);
resize(gray, dstImg, Size(64, 64));
std::vector<float> array;
if (dstImg.isContinuous())
array.assign(dstImg.data, dstImg.data + dstImg.total());
else{
for (int i = 0; i < dstImg.rows; ++i) {
array.insert(array.end(), dstImg.ptr<float>(i), dstImg.ptr<float>(i) + dstImg.cols);
}
}
//Set input blob
net.setInput(array);
//Make forward pass
Mat prob = net.forward();
I've got this error: vector subscript out of range.
Should I use another function instead setInput?

Invalid resolution dpi. tesseract

I have made some changes to an image such as histogram, dilation, gray scale, edge detection etc. to identify the number plate in an image.The below code is part of where i slice each charterer in the number plate and storing it in Mat. Now I'd like to use tesseract to identify each character. but instead tesseract throw this warning. " Warning. Invalid resolution 0 dpi. Using 70 instead." and OCR output is empty. Can anyone help me.
Note: for now i'm doing only for one pic. just to check whether is it working or not.
if (!Plate.empty())
{
imshow("Final Plate", Plate);
waitKey();
int x = OTSU(Plate);
Mat BlurBinary = ConvertToBinary(Plate, x);
Mat BinPlate = BlurBinary.clone();
imshow("BinaryBlurImg", BlurBinary);
waitKey();
vector<vector<Point>>contours2;
vector<Vec4i>hierachy2;
findContours(BlurBinary, contours2, hierachy2, RETR_EXTERNAL, CHAIN_APPROX_NONE, Point(0, 0));
Mat dst1 = Mat::zeros(BlurBinary.size(), CV_8UC3);
if (!contours1.empty()) {
int i = 0;
for (int i = 0; i < contours2.size(); i++) {
Scalar color((rand() & 255), (rand() & 255), (rand() & 255));
drawContours(dst1, contours2, i, color, CV_FILLED, 8, hierachy2);
}
}
Rect BlobRect2;
for (int i = 0; i < contours2.size(); i++) {
BlobRect2 = boundingRect(contours2[i]);
if (BlobRect2.height < 10)
{
drawContours(BinPlate, contours2, i, black, CV_FILLED, 8, hierachy2);
}
else
{
Mat character;
character = Plate(BlobRect2);
imshow("character", character);
waitKey();
imwrite(format("C:/Users/Di/source/repos/LPRrecognition/Characters/Img%d.tif", i), character);
}
}
}
else {
cout << "no plate sorry";
}
char *outText;
tesseract::TessBaseAPI *api = new tesseract::TessBaseAPI();
// Initialize tesseract-ocr with English, without specifying tessdata path
if (api->Init(NULL, "eng")) {
fprintf(stderr, "Could not initialize tesseract.\n");
exit(1);
}
// Open input image with leptonica library
Pix *image1 = pixRead("C:\\Users\\Di\\source\\repos\\LPRrecognition\\Characters\\Img1.tif");
api->SetImage(image1);
// Get OCR result
outText = api->GetUTF8Text();
printf("OCR output:\n%s", outText);
cout << outText;
// Destroy used object and release memory
api->End();
delete[] outText;
pixDestroy(&image1);

Issues with gpu::resize

I am trying to calculate HOG features on GPU for different levels and then I am saving features of each level to a yml file. Below is the function that I am using.
void App::run()
{
unsigned int count = 0;
FileStorage fs;
running = true;
int width = 640;
int height = 480;
Size win_size(args.win_width, args.win_width * 2);
Size win_stride(args.win_stride_width, args.win_stride_height);
cv::gpu::HOGDescriptor gpu_hog(win_size, Size(16, 16), Size(8, 8), Size(8, 8), 9,
cv::gpu::HOGDescriptor::DEFAULT_WIN_SIGMA, 0.2, gamma_corr,
cv::gpu::HOGDescriptor::DEFAULT_NLEVELS);
VideoCapture vc("/home/ubuntu/Desktop/getdescriptor/images/image%d.jpg");
Mat frame;
Mat Left;
Mat img_aux, img, img_to_show, img_new;
cv::Mat temp;
gpu::GpuMat gpu_img, descriptors, new_img;
char cbuff[20];
while (running)
{
vc.read(frame);
if (!frame.empty())
{
workBegin();
sprintf (cbuff, "%04d", count);
// Change format of the image
if (make_gray) cvtColor(frame, img_aux, CV_BGR2GRAY);
else if (use_gpu) cvtColor(frame, img_aux, CV_BGR2BGRA);
else Left.copyTo(img_aux);
// Resize image
if (args.resize_src) resize(img_aux, img, Size(args.width, args.height));
else img = img_aux;
img_to_show = img;
gpu_hog.nlevels = nlevels;
hogWorkBegin();
if (use_gpu)
{
gpu_img.upload(img);
new_img.upload(img_new);
fs.open(cbuff, FileStorage::WRITE);
//double scale = 1.05;
for(int levels = 0; levels < nlevels; levels++)
{
gpu_hog.getDescriptors(gpu_img, win_stride, descriptors, cv::gpu::HOGDescriptor::DESCR_FORMAT_ROW_BY_ROW);
descriptors.download(temp);
printf("size %d %d\n", temp.rows, temp.cols);
fs <<"level" << levels;
fs << "features" << temp;
cout<<"("<<width<<","<<height<<")"<<endl;
width = round(width/scale);
height = round(height/scale);
cout<<"Levels "<<levels<<endl;
if(width < win_size.width || height < win_size.height)
break;
resize(img,img_new,Size(width,height));
scale *= scale;
}
cout<<count<<endl;
count++;
}
hogWorkEnd();
fs.release();
}
else running = false;
}
}
For the first image it is correctly calculating HOG features for all levels but for the next image it takes the old value of width and height and in that case it break the following loop.
if(width < win_size.width || height < win_size.height)
break;
Can some one point my mistake. I tried to debug but unfortunately no success yet.
HOG feature calculation of each image takes old value of the following three parameters.
1. Width
2. Height
3. Scale
And when it calculates HOG features for next image it break the loop immediately. A common programming mistake.

opencv: single pixal assignment confusion

I am recently working with OpenCV and C++ for a project and I found a weird thing:
when I try to access single pixal value in IplImage and assign other value, it could run properly but the result is that it can only operate part of the whole image.
relevant code:
IplImage* output_frame = cvCreateImage(size, IPL_DEPTH_8U, 1);
IplImage* current_frame = cvCreateImage(size, IPL_DEPTH_8U, 1);
while((current_frame = cvQueryFrame(video_gray)) != 0 )
{
for (int row=0;row<height;row++)
{
uchar* ptr_current_frame = (uchar *)(current_frame->imageData+current_frame->widthStep*row);
uchar* ptr_output_frame = (uchar *)(output_frame->imageData+output_frame->widthStep*row);
for (int cols=0;cols<width;cols++)
{
//other codes...
ptr_output_frame[cols]=ptr_current_frame[cols];
}
}
}
The result is the left part of the image was copied to the output_frame. And when I run the following code:
IplImage* output_frame = cvCreateImage(size, IPL_DEPTH_8U, 1);
IplImage* current_frame = cvCreateImage(size, IPL_DEPTH_8U, 1);
while((current_frame = cvQueryFrame(video_gray)) != 0 )
{
for (int row=0;row<height;row++)
{
uchar* ptr_current_frame = (uchar *)current_frame->imageData+current_frame->width*row;
uchar* ptr_output_frame = (uchar *)output_frame->imageData+output_frame->width*row;
for (int cols=0;cols<width;cols++)
{
//other codes...
ptr_output_frame[cols]=ptr_current_frame[cols];
}
}
}
I got the upside part of the image in the output_frame.
I cannot get the the whole image copy in output_frame either way. Could anybody help me with this? Thanks a lot!
[updates] 05/16/2015
I have found out that output_frame->widthStep is different from current->widthStep after current_frame is executed in the following code:
current_frame = cvQueryFrame(video_gray);
It makes sense why the first part of the code wouldnt work. But I still dont know why the second part of the code doesnt work.
I now have my whole codes updated here and hope you can help me make this right. I am really appreciate your help.
CvCapture* video_gray = cvCreateFileCapture("test_gray.avi");
const double fps = cvGetCaptureProperty(video_gray, CV_CAP_PROP_FPS);
const int width = (int)cvGetCaptureProperty(video_gray, CV_CAP_PROP_FRAME_WIDTH);
const int height = (int)cvGetCaptureProperty(video_gray, CV_CAP_PROP_FRAME_HEIGHT);
const CvSize size = cvSize(width, height);
IplImage* current_frame = cvCreateImage(size, IPL_DEPTH_8U, 1);
IplImage* output_frame=cvCreateImage(size, IPL_DEPTH_8U, 1);
int flag = 0;
cvNamedWindow("test",1);
cvNamedWindow("test2",1);
while((current_frame = cvQueryFrame(video_gray)) != 0 )
{
cout<<flag++<<endl;
if(flag<500) continue;
for (int row=0;row<height;row++)
{
uchar* ptr_current_frame = (uchar *)(current_frame->imageData+current_frame->widthStep*row);
uchar* ptr_output_frame = (uchar *)(output_frame->imageData+output_frame->widthStep*row);
for (int cols=0;cols<width;cols++)
{
ptr_output_frame[cols]= ptr_current_frame[cols];
}
}
cvShowImage("test",output_frame);
cvShowImage("test2",current_frame);
cvWaitKey(10);
}
You don't handle the number of channels...
please try
IplImage* output_frame = cvCreateImage(size, IPL_DEPTH_8U, 1);
IplImage* current_frame = cvCreateImage(size, IPL_DEPTH_8U, 1);
while((current_frame = cvQueryFrame(video_gray)) != 0 )
{
for (int row=0;row<height;row++)
{
uchar* ptr_current_frame = (uchar *)(current_frame->imageData+current_frame->widthStep*row);
uchar* ptr_output_frame = (uchar *)(output_frame->imageData+output_frame->widthStep*row);
for (int cols=0;cols<width;cols++)
{
//other codes...
// here insead take care of the channels too. Only write ne channel to the output
ptr_output_frame[cols]=ptr_current_frame[cols*current_frame->nChannels];
}
}
}
but you should really try to switch to C++ API: try something like this:
cv::VideoCapture video = cv::VideoCapture("test_gray.avi");
int width = ...
int height = ...
cv::Mat image_captured;
cv::Mat image_gray; // if wanted
cv::Mat image_output1 = cv::Mat(height, width, CV_8UC1);
cv::Mat image_output2 = cv::Mat(height, width, CV_8UC1);
while(video.read(image_captured))
{
// if you want to convert the image to
if(image_captured.channels() > 1)
{
cv::cvtColor(image_captured, image_gray, CV_BGR2GRAY);
}
else
{
image_gray = image_captured;
}
[...]
for(int j=0; j<height; ++j)
{
for(int i=0; i<width; ++i)
{
image_output1.at<uchar>(j,i) = image_gray.at<uchar>(j,i); // read from single channel image
image_output1.at<uchar>(j,i) = image_captured.at<cv::Vec3b>(j,i)[0]; // only read the first channel of a multi-channel image
}
}
}
cv::imshow("output1", image_output1);
cv::imshow("output2", image_output2);
cv::imshow("input", image_capured);
cv::waitKey(0);
}
much easier to use, and you can still make it more efficient by using row-pointers in each iteration etc

VLC picture_t to IplImage and IplImage to picture_t

I'm trying to write VLC video filter using openCV to normalize video.
And I'm having troubles with VLC picture_t converting to IplImage and back to picture_t. IplImage is needed for transform to Mat and proceed with openCV tools. Couldn't find the solution elsewhere, so asking for help here.
The main function for transforming images is:
static picture_t *FilterNormalizeOpenCV( filter_t *p_filter, picture_t *p_pic )
{
Mat frame1;
IplImage* p_img1;
video_format_t fmt_out, fmt_in;
int i_planes = p_pic->i_planes;
CvSize sz = cvSize(abs(p_pic->format.i_width), abs(p_pic->format.i_height));
CvPoint pt1, pt2;
filter_sys_t *p_sys = p_filter->p_sys;
if ((!p_pic)) {
msg_Err( p_filter, "no image array" );
printf ("\n\n %s \n\n", "No p pic!!!");
return NULL;
}
i_planes = p_pic->i_planes;
if (i_planes<1) {
printf ("\n\n %s \n\n", "No image planes!!!");
msg_Err( p_filter, "no image planes" );
return NULL;
}
fmt_in = p_pic->format;
fmt_out = p_pic->format;
fmt_out.i_width = p_pic->format.i_width * p_sys->f_scale;
fmt_out.i_height = p_pic->format.i_height * p_sys->f_scale;
fmt_out.i_chroma = VLC_CODEC_BGRA;
p_sys->p_proc_image = image_Convert( p_sys->p_image, p_pic,
&(p_pic->format), &fmt_out );
p_sys->p_to_be_freed = p_sys->p_proc_image;
i_planes = p_sys->p_proc_image->i_planes;
for( int i = 0; i < i_planes; i++ )
{
sz = cvSize(abs(p_sys->p_proc_image->p[i].i_visible_pitch /
p_sys->p_proc_image->p[i].i_pixel_pitch),
abs(p_sys->p_proc_image->p[i].i_visible_lines));
p_sys->p_cv_image[i] = cvCreateImageHeader(sz, IPL_DEPTH_8U,
p_sys->p_proc_image->p[i].i_pixel_pitch);
cvSetData( p_sys->p_cv_image[i],
(char*)(p_sys->p_proc_image->p[i].p_pixels), p_sys->p_proc_image->p[i].i_pitch );
}
p_img1 = p_sys->p_cv_image[0];
frame1 = cvarrToMat(p_img1);
//Here we'll proceed Mat frame with openCV
//and convert it back ti IplImage
//p_img1 = new IplImage(frame1);
cvGetRawData(p_img1, (uchar **) & p_pic->p[0].p_pixels, NULL, &sz);
return p_pic;
}
So, for now, it only receives VLC picture_t, converts it to BGRA(for openCV purposes), converts it to IplImage and back to picture_t.
But, in result, comes smth messy, which I can't download here cause of low reputation (screenshot). Would appreciate any help.