I am reading the raw video data from the read buffer using
cv::Mat imgbuf(Size(640, 480), CV_8UC3, &mem[0], (640*3));
This variable imgbuf I am passing to face detection algorithm which detects the face & draws the rectangle around the face. after that I am getting output something like
I tried with below code where I am performing resize operation before pass to face detection algorithm. by using this method it is working fine. but without resizing function I am getting noticeable output with rectangle around the face.
while(1)
{
unsigned char *mem = (unsigned char*)mmap(NULL, page_offset + len,
PROT_READ |PROT_WRITE, MAP_PRIVATE, fd, page_base);
cv::Mat imgbuf(Size(640, 480), CV_8UC3, &mem[0], (640*3));
cv::resize(imgbuf,imgbuf,(640,480)); //Dummy function to get the right output.
auto result = v->facedetection(imgbuf);
for (const auto &r : result.rects) {
cv::rectangle(imgbuf,cv::Rect{ cv::Point(r.x * imgbuf.cols, r.y *
imgbuf.rows),cv::Size{(int)(r.width * imgbuf.cols), (int)(r.height *
imgbuf.rows) } },0xff);
}
imshow("face-detection", imgbuf);
waitKey(1);
can anybody help be to sort out this problem
Test this method:
unsigned char *mem = (unsigned char*)mmap(NULL, page_offset + len,
PROT_READ |PROT_WRITE, MAP_PRIVATE, fd, page_base);
cv::Mat imgbuf(480,640, CV_8UC3, &mem[0]);
cv::Mat img_2, img_3;
cv::resize(imgbuf,img_2,cv::Size(640,480));
img_2.copyTo(img_3);
auto result = v->facedetection(img_2);
for (const auto &r : result.rects)
{
cv::Rect myR = cv::Rect(r.x * img_2.cols, r.y * img_2.rows, (int)(r.width * img_2.cols),
(int)(r.height * img_2.rows));
cv::rectangle(img_3,myR,Scalar(0, 0, 255), 1);
}
imshow("Result", img_3);
waitKey(0);
After getting a valid result you can optimize this and use less of "Mat"s.
Related
I have 2 images with transparency. Images have the same format and size.
How can I copy pixels from second image to the first one by using C++ OpenCV?
The idea is to draw 2nd image on the 1st image.
Thanks
code from the link in comment above (modified for my case)
L. Scott Johnson thanks you again!
void alphaBlend(Mat& foreground, Mat& background, Mat& alpha, Mat& outImage)
{
// Find number of pixels.
int numberOfPixels = foreground.rows * foreground.cols * foreground.channels();
// Get floating point pointers to the data matrices
float* fptr = reinterpret_cast<float*>(foreground.data);
float* bptr = reinterpret_cast<float*>(background.data);
float* aptr = reinterpret_cast<float*>(alpha.data);
float* outImagePtr = reinterpret_cast<float*>(outImage.data);
// Loop over all pixesl ONCE
for (
int i = 0;
i < numberOfPixels;
i++, outImagePtr++, fptr++/*, aptr++*/, bptr++
)
{
if (i!= 0 && (i % 3) == 0)
aptr++;
*outImagePtr = (*fptr) * (*aptr) + (*bptr) * (1 - *aptr);
}
}
void Mix()
{
Mat layer = imread("images\\leyer.png", IMREAD_UNCHANGED);
Mat image = imread("images\\bg.jpg");
std::vector<cv::Mat> bgra_planes;
cv::split(layer, bgra_planes);
Mat alpha = bgra_planes[3];
bgra_planes.pop_back();
cv::merge(bgra_planes, layer);
alpha.convertTo(alpha, CV_32FC3, 1.0 / 255);
layer.convertTo(layer, CV_32FC3);
image.convertTo(image, CV_32FC3);
Mat result(layer.size(), CV_32FC3);
alphaBlend(layer, image, alpha, result);
result.convertTo(result, CV_8UC3);
// previous tries
//cv::copyTo(layer, image, );
//cv::addWeighted(image, 1, layer, 1, 0.5, result);
String windowName = "alpha blending";
namedWindow(windowName, WINDOW_NORMAL);
imshow(windowName, result);
waitKey(0);
destroyWindow(windowName);
}
Here's what you can try:
load your first image
cv::Mat img = cv::imread("img.jpeg");
find your smaller image - here I'm just resizing the same image
cv::Mat img_resize;
cv::resize(img, img_resize, cv::Size(), 0.3, 0.3);
choose the xy origin location
const cv::Point origin(100, 100);
create a Region of Interest
cv::Rect roi(origin, img_resize.size());
copy the matrix data in
img_resize.copyTo(img(roi));
I'm trying to get the centers of the clusters from a depth frame, but can't the correct coordinates. I'm following a example given on stack overflow example, but my matrix is 512*424 of type CV_16SC1 (ushort, one channel).
No matter what i do, i get the wrong or none center's return (on the left top corner instead of middle center). Can anyone explains to me how to do it?
Here is a sample of the original and output: images
//my code so far:
FILE *infile= NULL;
fopen_s(&infile, p1ficheiro, "rb"); //if... blá blá
unsigned short *buffer = new unsigned short[512*424];
fread(buffer, 512 * 424, sizeof(unsigned short), infile)
//entry matrix
Mat frame(424,512,CV_16SC1,buffer);
int dimension = 8;
//working Mat
Mat temp;
frame.copyTo(temp);
temp.convertTo(temp, CV_32FC1);
temp.reshape(dimension , (512 * 424) / dimension );
//going to kmeans...
Mat labels, centers;
kmeans(temp, dimension , labels, TermCriteria(CV_TERMCRIT_ITER | CV_TERMCRIT_EPS, 1000,0.001), 10, KMEANS_RANDOM_CENTERS, centers);
//finding centers
for (int j = 0; j < centers.rows; ++j)
{
std::cout << centers.row(j) << std::endl;
circle(temp, Point(centers.at<float>(j, 0), centers.at<float>(j, 1)), 30, Scalar::all(255), 2);
}
//just so it's more clear to the eye
frame.convertTo(frame, CV_16SC1, 8);
imshow("IN",frame);
imshow("OUT",temp);
waitkey(0);
//... close and free everything...
I am going to use the grabcutNPP from cuda sample in order to speed up the image processing. The original sample code is implemented for FIBITMAP, but my input/output type will be Mat.
I had figured out most of the code but stuck in the cudaMemcpyDeviceToHost step...As a CUDA beginner, I have no reason why it always stops at this step
Here is part of my code :
void grabcutGPU(Mat& _src, Mat& _dst, Rect _srcRect){
GrabCut *grabcut;
const size_t width = _src.rows;
const size_t height = _src.cols;
size_t image_pitch;
size_t result_pitch;
size_t trimap_pitch;
uchar4 *gpu_src, *gpu_dst;
unsigned char *d_trimap;
NppiRect rect;
// rect to nppirect
rect.x = _srcRect.x;
rect.y = _srcRect.y;
rect.width = _srcRect.width;
rect.height = _srcRect.height;
//melloc for src_image
checkCudaErrors(cudaMallocPitch(&gpu_src, &image_pitch, width * sizeof(uchar4), height));
checkCudaErrors(cudaMemcpy2D(gpu_src, image_pitch, _src.ptr<uchar4>(), width * sizeof(uchar4), width * sizeof(uchar4), height, cudaMemcpyHostToDevice));
// melloc foe rect
checkCudaErrors(cudaMallocPitch(&d_trimap, &trimap_pitch, width, height));
// Setup GrabCut
grabcut = new GrabCut(gpu_src, (int)image_pitch, d_trimap, (int)trimap_pitch, width, height);
//rect to memory
checkCudaErrors(TrimapFromRect(d_trimap, (int)trimap_pitch, rect, width, height));
//grabcut segmentation
grabcut->computeSegmentationFromTrimap();
//melloc for dst_image
checkCudaErrors(cudaMallocPitch(&gpu_dst, &result_pitch, width * 4, height));
//GPU process
checkCudaErrors(ApplyMatte(2, gpu_dst, (int)result_pitch, gpu_src, (int)image_pitch, grabcut->getAlpha(), grabcut->getAlphaPitch(), width, height));
size_t output_pitch = result_pitch;
//send result to dst
checkCudaErrors(cudaMemcpy2D(_dst.ptr(), (int)output_pitch, gpu_dst, result_pitch, width * 4, height, cudaMemcpyDeviceToHost));
delete grabcut;
checkCudaErrors(cudaDeviceSynchronize(), "Kernel Launch Failed");
checkCudaErrors(cudaFree(gpu_src), "CUDA Free Failed");
checkCudaErrors(cudaFree(gpu_dst));
checkCudaErrors(cudaFree(d_trimap), "CUDA Free Failed");}
This question is solved.
First of all, the row and col are carelessly mistaken.
Then, the input mat were 3 channels but this function needs 4 channels mat for passing result. It could be solved by converting colour type.
Thanks to Micka, or I might never notice the channel problem.
This question already has an answer here:
Efficiently load a large Mat into memory in OpenCV
(1 answer)
Closed 6 years ago.
This feels like a really easy question, but I have not been able to find the answer to it.
I have a function which reads a (binary) file and feeds the content into an openCV image. Currently the file is always of the "unsigned char" datatype but I would like to expand the support to other datatypes. Preferable as an argument to the function.
I'm not very experienced with C++ but after googling around this feels like something which should be done with templates, but I am really unsure how to implement it.
cv::Mat ReadImage(const char * filename, int dataTypeSize, int imageWidth)
{
auto read_image = fopen(filename, "rb");
if (read_image == nullptr)
{
printf("Image Not Found\n");
return cv::Mat();
}
fseek(read_image, 0, SEEK_END);
int fileLen = ftell(read_image);
fseek(read_image, 0, SEEK_SET);
auto pre_image = static_cast<unsigned char *>(malloc(fileLen));
auto data = fread(pre_image, 1, fileLen, read_image);
// Printed and verify the values
//printf("File Size %d\n", fileLen);
//printf("Read bytes %zd\n", data);
auto width = imageWidth;
auto height = fileLen / dataTypeSize / imageWidth;
fclose(read_image);
vector<unsigned char> buffer(pre_image, pre_image + data);
auto img = cv::Mat(height, width, CV_64F, pre_image);
//printf("Image rows %d\n", img.rows);
//printf("Image cols %d\n", img.cols);
return img;
}
cv::Mat is not a template class. You can construct a different cv::Mat simply by supplying a different type parameter to the constructor (currently hardcoded as CV_64F).
Like this:
cv::Mat ReadImage(const char * filename, int dataTypeSize, int imageWidth, int type)
{
. . .
auto img = cv::Mat(height, width, type, pre_image);
return img;
}
auto mat = ReadImage("abc", 8, 1000, CV_32S);
I have some code to create an HSV mask that looks approximately like this (taken from this Japanese-language page):
void colorExtraction(const cv::gpu::GpuMat &src,
cv::gpu::GpuMat *dst)
{
cv::Mat lut(256, 1, CV_8UC3);
for (int i = 0; i < 256; i++)
{
cv::Vec3b thisHSV;
thisHSV[0] = inHRange(i) ? 255 : 0;
thisHSV[1] = inSRange(i) ? 255 : 0;
thisHSV[2] = inVRange(i) ? 255 : 0;
lut.at<cv::Vec3b>(i) = thisHSV;
}
/* apply LUT to input image */
cv::gpu::GpuMat extracted(src.size(), CV_8UC3);
cv::gpu::LUT(src, lut, extracted);
/* divide image into each channel */
std::vector<cv::gpu::GpuMat> channels;
cv::gpu::split(extracted, channels);
/* create mask */
cv::gpu::bitwise_and(channels[0], channels[1], *dst);
cv::gpu::bitwise_and(*dst, channels[2], *dst);
}
This works, but despite the operations being mostly in the GPU, it is slower than I would like, perhaps due to a number of intermediate GpuMats. I suspect there might be a nice way to fold this all up into just one or two calls, but I don't know what it could be. Writing my own CUDA kernel is, of course, an option, but I want to check to see if I don't need to reinvent the wheel.
To self-answer, I ended up coding my own kernel to do the LUT(), split(), and two bitwise_and()s in a single call:
__global__ void colorExtractionKernel(cv::gpu::PtrStepSz<uchar3> const src,
cv::gpu::PtrStepSz<unsigned char> dst,
cv::gpu::PtrStepSz<uchar3> const lut)
{
unsigned int row = blockIdx.y * blockDim.y + threadIdx.y;
unsigned int col = blockIdx.x * blockDim.x + threadIdx.x;
// Extract post-LUT hsv flags
uchar3 srcHSV = src(row, col);
unsigned char h = lut(srcHSV.x, 0).x;
unsigned char s = lut(srcHSV.y, 0).y;
unsigned char v = lut(srcHSV.z, 0).z;
// Result pixel is the AND of the pixels
dst(row, col) = (h & s & v);
}
void colorExtraction_cuda(const cv::gpu::GpuMat &src, // input HSV image
cv::gpu::GpuMat &dst, // specified color extracted binarized image
cv::Mat const &lut) // Look-up thresholds
{
cudaStream_t thisStream;
gpuErrChk(cudaStreamCreate(&thisStream));
dim3 Threads(32, 16);
dim3 Blocks((src.cols + Threads.x - 1)/Threads.x, (src.rows + Threads.y - 1)/Threads.y);
cv::gpu::GpuMat gpuLut(lut);
colorExtractionKernel<<<Blocks, Threads, 0, thisStream>>>(src, dst, gpuLut);
gpuErrChk(cudaStreamSynchronize(thisStream));
gpuErrChk(cudaStreamDestroy(thisStream));
gpuErrChk(cudaGetLastError());
}