Transforming annotations for an object in an image - image

I've certain data set of images which has annotations for objects in that image. Annotations as in [xmin, xmax, ymin, ymax] for the object in the image. How do I transform these coordinates to their new values when I resize the image while maintaining the aspect ratio ?

If you are simply resizing, use resize. For example:
using namespace cv;
Mat img;
img = imread("image.jpg", CV_LOAD_IMAGE_COLOR);
Mat dst;
resize(img, dst, Size(xmax-xmin,ymax-ymin));
If you are extracting sub image, use Rect. For example:
using namespace cv;
Mat original_img;
Rect roi;
roi.x = xmin;
roi.y = ymin;
roi.width = xmax-xmin;
roi.height = ymax-ymin;
Mat subimage = original_img(roi);
If you are trying to find out the coordinates(xmin,xmax,ymin,ymax) after resize,
multiply them by the factor of the resize.
For example, if the resize is by the factor of 0.5,
the coordinates(xmin,xmax,ymin,ymax) are now (xmin*0.5,xmax*0.5,ymin*0.5,ymax*0.5).

you can use this package too: https://github.com/italojs/resize_dataset_pascalvoc
it's easy to use python3 main.py -p <IMAGES_&_XML_PATH> --output <IMAGES_&_XML> --new_x <NEW_X_SIZE> --new_y <NEW_X_SIZE> --save_box_images <FLAG>"

Related

Crop and save an image in Flutter without ui

I want to make an app that can crop image in a specific aspect ratio(device ratio).
But, i don't want any ui to show crop options.
Ok, here is an example,
If user tap on an image from the image list in the app the selected Image automatically (background process) crop (device ratio) & saved on the device without showing any crop related ui. How can i do this! Any function in dart by whom can crop an image without showing anything.
You can use copyCrop() with image:
Image copyCrop(Image src, int x, int y, int w, int h);
import 'dart:io';
import 'package:image/image.dart';
void main(List<String> argv) {
String path = argv[0];
Directory dir = Directory(path);
List files = dir.listSync();
List<int> trimRect;
for (var f in files) {
if (f is! File) {
continue;
}
List<int> bytes = f.readBytesSync();
Image image = decodeImage(bytes);
if (image == null) {
continue;
}
if (trimRect == null) {
trimRect = findTrim(image, mode: TrimMode.transparent);
}
Image trimmed = copyCrop(image, trimRect[0], trimRect[1],
trimRect[2], trimRect[3]);
String name = f.path.split(RegExp(r'(/|\\)')).last;
File('$path/trimmed-$name').writeBytesSync(encodeNamedImage(image, f.path));
}
}
I can confirm that Jim's answer is correct. Only thing I'd like to add to his answer is how to use the findTrim() method, which the docs don't explain properly. The key to use findTrim is to have an a sample image with target aspect ratio but it should also include base negative space as background. The findTrim() function basically takes information from a sample image and you can get the x,y coordinates as well as width,height if you don't want to manually calculate the x,y coordinates. The keyword here is negative space because if you just provide a target picture(say 4:3) to the findTrim() method, the function will simply crop the image from x,y coordinates which are 0,0 in this case. Having negative space that acts as place holder will make your work easier to clip the image.
For example to auto crop any 16:9 image to 4:3, have a 4:3 sample image with 16:9 negative space background. I have added the image as well which you can save to see for yourself.

Do I need all these statements to get the data array of an image in HTML5 canvas?

I am loading a pixel font file as a png image. I then use it to draw each character to canvas by writing to the buffer imageData.data clamped array and then using putImageData.
Is there a simpler way to get the data array from the png image apart from loading the image as fontImage and then these 7 lines ...
let fontCanvas = document.createElement("canvas");
fontCanvas.width = fontImage.width;
fontCanvas.height = fontImage.height;
let fontContext = fontCanvas.getContext("2d");
fontContext.drawImage(fontImage, 0, 0);
let fontBank = fontContext.getImageData(0,0,fontCanvas.width,fontCanvas.height);
let fontData = fontBank.data;
Thanks.

How to crop an Image using CvRect in Open CV.

I want to crop an image of 1176*640 to save the ROI of 1176*400 size. I am using the following snippet to acheive bit I am still getting the original image as output.
IplImage *CMyFunction::ROI(IplImage *pImage, CvRect ROI)
{
IplImage *mROI = cvCreateImage(cvGetSize(*pImage), IPL_DEPTH_8U, 1);
cvSetImageROI(pImage, rect_ROI);
cvCopy(pImage, mROI);
cvResetImageROI(pImage);
return mROI;
}
For cvCopy() the source and destination should be same size and type, that is the parameter like width, height, depth, and number of channel should be equal for both image. In your case you can change your code either like
IplImage *mROI = cvCreateImage(cvGetSize(pImage), pImage->depth, pImage->nChannels); //create dest with same size as source
cvSetImageROI(pImage, rect_ROI); //Set roi on source
cvSetImageROI(mROI, rect_ROI); //set roi on dest
cvCopy(pImage, mROI);
cvResetImageROI(pImage);
cvResetImageROI(mROI);
or
IplImage *mROI = cvCreateImage(cvSize(rect_ROI.width,rect_ROI.height), pImage->depth, pImage->nChannels); // create an image of size as rect
cvSetImageROI(pImage, rect_ROI); //set roi on source
cvCopy(pImage, mROI);
cvResetImageROI(pImage);
I understood that the pointer when leaves the function is no longer stable and declared a new IplImage* outside of the function and pass it as a parameter which proved to be efficient.
IplImage *CMyFunction::ROI(IplImage *pImage, CvRect ROI, IplImage* FinalImage)

opencv: change image size without effecting content size

I am getting image containing character after applying my image process. All these images (having character as content) have different size. I want to resize all images in same size without effecting it's content size. see below image:
http://techsture.com/img.jpg
I have tried some function to merge my source image with other white image but it needs both source images with same size. I need common size of images for further process.
Please guide me how can I convert my images to common size ??
Thank you
I would make a new image with the destination size, set a ROI in this new image to where you want the source image to show. Then use cvResize.
It should look something like:
int newWidth = 100;
int newHeight = 100;
CvRect rect;
IplImage* source = cvLoadImage("c:/myimage");
IplImage* dest = cvCreateImage(cvSize(newWidth,newHeight),source->depth,source->nChannels);
rect.x = newWidth/2 - source->width/2;
rect.y = newHeight/2 - source->height/2;
rect.width = source->width;
rect.height = source->height;
cvSetImageROI(dest,rect);
cvResize(source,dest);
cvResetImageROI(dest);

How to render a scaled SVG to a QImage?

There is a QSvgRenderer class in QtSvg module which can render image onto QPaintDevice. This one can be QImage. In that case we will create:
Image svgBufferImage(renderer.defaultSize(), QImage::Format_ARGB32);
But how to render to a QImage of different size than default from the SVG renderer? Since the SVG format image can be scaled without quality loss, is it possible to generate static images, like PNG, from SVG files using QSvgRenderer?
Does anyone have a better idea? Basically I need to create images like PNG from SVG files in different sizes.
Just give your QImage the desired size. The SVG renderer will scale to fit the whole image.
#include <QApplication>
#include <QSvgRenderer>
#include <QPainter>
#include <QImage>
// In your .pro file:
// QT += svg
int main(int argc, char **argv)
{
// A QApplication instance is necessary if fonts are used in the SVG
QApplication app(argc, argv);
// Load your SVG
QSvgRenderer renderer(QString("./svg-logo-h.svg"));
// Prepare a QImage with desired characteritisc
QImage image(500, 200, QImage::Format_ARGB32);
image.fill(0xaaA08080); // partly transparent red-ish background
// Get QPainter that paints to the image
QPainter painter(&image);
renderer.render(&painter);
// Save, image format based on file extension
image.save("./svg-logo-h.png");
}
This will create an 500x200 PNG image from the passed in SVG file.
Example output with an SVG image from the SVG logos page:
Here is complete answer:
QImage QPixmap::toImage()
If the pixmap has 1-bit depth, the returned image will also be 1 bit deep. Images with more bits will be returned in a format closely represents the underlying system. Usually this will be QImage::Format_ARGB32_Premultiplied for pixmaps with an alpha and QImage::Format_RGB32 or QImage::Format_RGB16 for pixmaps without alpha.
QImage img = QIcon("filepath.svg").pixmap(QSize(requiredsize)).toImage()
Also copy from above answer
// Save, image format based on file extension
image.save("./svg-logo-h.png");
If you have simple svg, like icon or small image, for replacing color for example, it's better to use NanoSVG lib
It has Qt wrapper, coded by me Qt Svg Render.
It's very small, only 2 headers and one cpp.
Usage:
QString svgPath="your svg Path";
QString pngPath="path for png";
QSize imageSize(your image Path size);
const QSize resultSize(size that you want to get);
QImage image(sizeW, sizeH, Format);//End of param
QFile svgFile(svgPath);
if (svgFile.open(QIODevice::ReadOnly))
{
int svgFileSize=svgFile.size();
QByteArray ba;
ba.resize(svgFileSize + 1);
svgFile.read(ba.data(), svgFileSize);
ba.back() = {};
if (auto const nsi(nsvgParse(ba.data(), "px", 96)); nsi)
{
image.fill(Qt::transparent);
QPainter p(&image);
p.setRenderHint(QPainter::Antialiasing, true);
drawSVGImage(&p, nsi, resultSize.width(), resultSize.height());
nsvgDelete(nsi);
image.save(pngPath);// if you want to save image
}
}

Resources