I want to add a text on an given co-ordinates of an image using the gocv library (also the text should expand from the co-ordinates; not from left to right).
Using the below command I was able to achieve both requirements. How can I load a custom .ttf font file and do the same thing ?
import (
"fmt"
"image"
"image/color"
"os"
"github.com/gofiber/fiber/v2"
"gocv.io/x/gocv"
)
func GeneralRoutes(gen fiber.Router) {
gen.Get("/image", func(c *fiber.Ctx) error {
imageFile := "path/input.png"
outputFile := "path/output.jpg"
img := gocv.IMRead(imageFile, gocv.IMReadColor)
if img.Empty() {
fmt.Printf("Error opening image: %s\n", imageFile)
os.Exit(1)
}
// Create a font type and scale
font := gocv.FontHersheyPlain
scale := 5.5
thickness := 5
// Define the text to be added, position, font type and color
text := "Hello World"
textSize := gocv.GetTextSize(text, font, scale, thickness)
textPos := img.Point{X: 1170 - textSize.X/2, Y: 663 - textSize.Y/2}
gocv.PutText(&img, text, textPos, font, scale, color.RGBA{0, 0, 0, 0}, thickness)
// Save the output image
gocv.IMWrite(outputFile, img)
return c.SendFile(outputFile)
})
}
Related
This is the part where the image set to the picture controller:
void CMFCApplication3View::drawImg1(Mat img) {
int nX = img.rows;
int nY = img.cols;
CImage image;
Mat2CImage(&img, image);
CRect rect;//픽쳐 컨트롤의 크기를 저장할 CRect 객체
pictureControl.GetWindowRect(rect);//GetWindowRect를 사용해서 픽쳐 컨트롤의 크기를 받는다.
CDC* dc; //픽쳐 컨트롤의 DC를 가져올 CDC 포인터
dc = pictureControl.GetDC(); //픽쳐 컨트롤의 DC를 얻는다.
image.StretchBlt(dc->m_hDC, 0, 0, nX, nY, SRCCOPY);//이미지를 픽쳐 컨트롤 크기로 조정 rect.Width(), rect.Height()
ReleaseDC(dc);//DC 해제
}
void CMFCApplication3View::drawImg2(Mat img) {
int nX = img.rows;
int nY = img.cols;
CImage image;
Mat2CImage(&img, image);
CRect rect;//픽쳐 컨트롤의 크기를 저장할 CRect 객체
pictureControl2.GetWindowRect(rect);//GetWindowRect를 사용해서 픽쳐 컨트롤의 크기를 받는다.
CDC* dc; //픽쳐 컨트롤의 DC를 가져올 CDC 포인터
dc = pictureControl2.GetDC(); //픽쳐 컨트롤의 DC를 얻는다.
image.StretchBlt(dc->m_hDC, 0, 0, nX, nY, SRCCOPY);//이미지를 픽쳐 컨트롤 크기로 조정 rect.Width(), rect.Height()
ReleaseDC(dc);//DC 해제
}
You don't even attempt to stretch the image to the destination rectangle in this piece of code, you just draw it to a rectangle equal to the image dimensions, which is not a stretch. You get the destination rectangle, but do nothing with it.
You should better implement some "best-fit" algorithm, ie stretch the image to the maximum possible dimensions, occupying either the whole width or the whole height of the destination rectangle, while maintaining its original proportions, ie not distorting it. Here is some code:
CRect rect;
picturecontrol.GetClientRect(rect);
int nImgW = img.cols, nImgH = img.rows; // Original image dimensions
int nCtlW = rect.Width(), nCtlH = rect.Height(); // Destination control dimensions
int nW, nH; // Stretched (draw) dimensions
if (nImgW*nCtlH > nCtlW*nImgH)
{ // Image is proportionately wider than the control, fit it horizontally
nW = nCtlW;
nH = MulDiv(nW, nImgH, nImgW);
}
else
{ // Image is proportionately taller than the control, fit it vertically
nH = nCtlH;
nW = MulDiv(nH, nImgW, nImgH);
}
image.StretchBlt(dc->m_hDC, 0, 0, nW, nH, SRCCOPY);
To determine whether the image is proportionately wider or taller than the destination rectangle the condition originally was of course nImgW/nImgH > nCtlW/nCtlH, but was changed to what is shown in the code above, so as to avoid possible inaccuracies due to integer division (it returns the integer quotient, rather than a rounded value, and has a smaller range too).
A side note, normally you should draw your images in response to the WM_PAINT message (in the OnDraw(), OnPaint() or the controls' OnPaint() events), using the CDC* passed to the function or calling CPaintDC. These call BeginPaint()/EndPaint() instead of GetDC()/ReleaseDC() - you must invalidate the control to trigger a repaint. For a static picture control you can call ctl.SetBitmap() (this in any other point in your code, not while processing WM_PAINT).
How do i convert alpha channel of the image to white color using gocv? Sorry, I would'nt find the documentation.
package main
import (
"fmt"
"os"
"gocv.io/x/gocv"
)
func main() {
inputs := "test.png"
img := gocv.IMRead(inputs, gocv.IMReadUnchanged)
defer img.Close()
if img.Empty() {
fmt.Printf("cannot read image %s\n", inputs)
os.Exit(1)
}
// how to convert alpha channel of the image to white color
gocv.Split(img)
}
I was trying to make a fullscreen window in OpenCV and the functions provided in OpenCV are working except there is a white edge in the left border and top border. After spending time in investigating the code in OpenCV, I found out that the function getWindowImageRect is somehow returning a value that is 1px more in x, y and 1px less in width and height than the function that I have wrote.
Okay, and here is the question. Why are the two functions returning different values?
Here is the code I have found in OpenCV:
CvRect cvGetWindowRect_W32(const char* name)
{
CvRect result = cvRect(-1, -1, -1, -1);
CV_FUNCNAME( "cvGetWindowRect_W32" );
__BEGIN__;
CvWindow* window;
if (!name)
CV_ERROR( CV_StsNullPtr, "NULL name string" );
window = icvFindWindowByName( name );
if (!window)
EXIT; // keep silence here
RECT rect;
GetClientRect(window->hwnd, &rect);
{
POINT pt = {rect.left, rect.top};
ClientToScreen(window->hwnd, &pt);
result = cvRect(pt.x, pt.y, rect.right - rect.left, rect.bottom - rect.top);
}
__END__;
return result;
}
This is the code that I have wrote in Python, which I thought will give me the same result:
def getWindowRect(name)
hwnd = win32gui.FindWindow(None, name)
rect_l, rect_t, rect_r, rect_b = win32gui.GetClientRect(hwnd)
pt_x, pt_y = win32gui.ClientToScreen(hwnd, (rect_l, rect_t))
result = (pt_x, pt_y, rect_r - rect_l, rect_b - rect_t)
return result
The result of using the two above functions give me output like this:
(1, 1, 2559, 1439)
(0, 0, 2560, 1440)
So I wonder if any one can tell me why is this happening?
Note that the test is performed under Windows 10.
I used TStatusBar and set style to "psOwnerDraw" to fill custom color on it.
There is no problem to display text in normal case but after I changed the resolution on Windows or moved application out of screen and back, the text is corrupted with some other text.
Here's my code:
void __fastcall TMainForm::TotalStatusBarDrawPanel(TStatusBar * StatusBar,
TStatusPanel * Panel, const TRect & Rect)
{
TRect StatusFillRect = Rect;
TCanvas& pCan = *StatusBar->Canvas;
if (Panel->Index == 0)
{
pCan.Font->Color = clRed;
pCan.Brush->Color = clBtnFace;
}
pCan.FillRect(StatusFillRect);
DrawTextW(pCan.Handle, Panel->Text.c_str(), -1,
&StatusFillRect, DT_SINGLELINE | DT_VCENTER);
}
How can I make something like this in Delphi:
I know I can make it from 3 tables so it would be easier, but how can I make Table cells split & merge and how to get the text to turn 90deg.?
Is there some good content libraries that have split & merge built in?
Check out woll2woll or infopower. They will do the grid for sure. The font can be achieved by overriding the OnDrawDataCell, OnDrawGroupHeaderCell and OnDrawTitleCell events and writing the text with rotated font.
{****************************************************************
* Create angled font. Procedure writen by Keith Wood *
****************************************************************}
procedure CreateAngledFont (AFont : TFont; const AAngle : Integer);
var
FntLogRec: TLogFont { Storage area for font information } ;
begin
{ Get the current font information. We only want to modify the angle }
fillchar (FntLogRec, sizeof(FntLogRec), #0);
GetObject (AFont.Handle, SizeOf(FntLogRec), Addr(FntLogRec));
{ Modify the angle. "The angle, in tenths of a degrees, between the base
line of a character and the x-axis." (Windows API Help file.) }
FntLogRec.lfEscapement := (AAngle * 10);
FntLogRec.lfOrientation := (AAngle * 10);
FntLogRec.lfOutPrecision := OUT_TT_PRECIS; { Request TrueType precision }
{ Delphi will handle the deallocation of the old font handle }
AFont.Handle := CreateFontIndirect (FntLogRec);
end;