ATV Modulator: text overlay for still images

This commit is contained in:
f4exb 2017-03-12 15:10:59 +01:00
parent e24c7bcf2c
commit b42d39108a
5 changed files with 168 additions and 6 deletions

View File

@ -31,6 +31,8 @@ MESSAGE_CLASS_DEFINITION(ATVMod::MsgReportVideoFileSourceStreamTiming, Message)
MESSAGE_CLASS_DEFINITION(ATVMod::MsgReportVideoFileSourceStreamData, Message) MESSAGE_CLASS_DEFINITION(ATVMod::MsgReportVideoFileSourceStreamData, Message)
MESSAGE_CLASS_DEFINITION(ATVMod::MsgConfigureCameraIndex, Message) MESSAGE_CLASS_DEFINITION(ATVMod::MsgConfigureCameraIndex, Message)
MESSAGE_CLASS_DEFINITION(ATVMod::MsgReportCameraData, Message) MESSAGE_CLASS_DEFINITION(ATVMod::MsgReportCameraData, Message)
MESSAGE_CLASS_DEFINITION(ATVMod::MsgConfigureOverlayText, Message)
MESSAGE_CLASS_DEFINITION(ATVMod::MsgConfigureShowOverlayText, Message)
const float ATVMod::m_blackLevel = 0.3f; const float ATVMod::m_blackLevel = 0.3f;
const float ATVMod::m_spanLevel = 0.7f; const float ATVMod::m_spanLevel = 0.7f;
@ -50,7 +52,8 @@ ATVMod::ATVMod() :
m_videoPrevFPSCount(0), m_videoPrevFPSCount(0),
m_videoEOF(false), m_videoEOF(false),
m_videoOK(false), m_videoOK(false),
m_cameraIndex(-1) m_cameraIndex(-1),
m_showOverlayText(false)
{ {
setObjectName("ATVMod"); setObjectName("ATVMod");
scanCameras(); scanCameras();
@ -489,6 +492,34 @@ bool ATVMod::handleMessage(const Message& cmd)
getOutputMessageQueue()->push(report); getOutputMessageQueue()->push(report);
} }
} }
else if (MsgConfigureOverlayText::match(cmd))
{
MsgConfigureOverlayText& cfg = (MsgConfigureOverlayText&) cmd;
m_overlayText = cfg.getOverlayText().toStdString();
return true;
}
else if (MsgConfigureShowOverlayText::match(cmd))
{
MsgConfigureShowOverlayText& cfg = (MsgConfigureShowOverlayText&) cmd;
bool showOverlayText = cfg.getShowOverlayText();
if (!m_imageFromFile.empty())
{
m_imageFromFile.copyTo(m_imageOriginal);
if (showOverlayText) {
qDebug("ATVMod::handleMessage: overlay text");
mixImageAndText(m_imageOriginal);
} else{
qDebug("ATVMod::handleMessage: clear text");
}
resizeImage();
}
m_showOverlayText = showOverlayText;
return true;
}
else else
{ {
return false; return false;
@ -621,11 +652,17 @@ void ATVMod::applyStandard()
void ATVMod::openImage(const QString& fileName) void ATVMod::openImage(const QString& fileName)
{ {
m_imageOriginal = cv::imread(qPrintable(fileName), CV_LOAD_IMAGE_GRAYSCALE); m_imageFromFile = cv::imread(qPrintable(fileName), CV_LOAD_IMAGE_GRAYSCALE);
m_imageOK = m_imageOriginal.data != 0; m_imageOK = m_imageFromFile.data != 0;
if (m_imageOK) if (m_imageOK)
{ {
m_imageFromFile.copyTo(m_imageOriginal);
if (m_showOverlayText) {
mixImageAndText(m_imageOriginal);
}
resizeImage(); resizeImage();
} }
} }
@ -802,3 +839,22 @@ void ATVMod::getCameraNumbers(std::vector<int>& numbers)
getOutputMessageQueue()->push(report); getOutputMessageQueue()->push(report);
} }
} }
void ATVMod::mixImageAndText(cv::Mat& image)
{
int fontFace = cv::FONT_HERSHEY_PLAIN;
double fontScale = image.rows / 100.0;
int thickness = 3;
int baseline=0;
qDebug("ATVMod::mixImageAndText: fontScale: %f m_overlayText: %s", fontScale, m_overlayText.c_str());
cv::Size textSize = cv::getTextSize(m_overlayText, fontFace, fontScale, thickness, &baseline);
baseline += thickness;
// position the text in the top left corner
cv::Point textOrg(2, textSize.height+4);
// then put the text itself
cv::putText(image, m_overlayText, textOrg, fontFace, fontScale, cv::Scalar::all(255*m_running.m_uniformLevel), thickness, CV_AA);
}

View File

@ -256,6 +256,48 @@ public:
{ } { }
}; };
class MsgConfigureOverlayText : public Message
{
MESSAGE_CLASS_DECLARATION
public:
const QString& getOverlayText() const { return m_overlayText; }
static MsgConfigureOverlayText* create(const QString& overlayText)
{
return new MsgConfigureOverlayText(overlayText);
}
private:
QString m_overlayText;
MsgConfigureOverlayText(const QString& overlayText) :
Message(),
m_overlayText(overlayText)
{ }
};
class MsgConfigureShowOverlayText : public Message
{
MESSAGE_CLASS_DECLARATION
public:
bool getShowOverlayText() const { return m_showOverlayText; }
static MsgConfigureShowOverlayText* create(bool showOverlayText)
{
return new MsgConfigureShowOverlayText(showOverlayText);
}
private:
bool m_showOverlayText;
MsgConfigureShowOverlayText(bool showOverlayText) :
Message(),
m_showOverlayText(showOverlayText)
{ }
};
ATVMod(); ATVMod();
~ATVMod(); ~ATVMod();
@ -452,7 +494,8 @@ private:
Real m_peakLevel; Real m_peakLevel;
Real m_levelSum; Real m_levelSum;
cv::Mat m_imageOriginal; //!< original non resized image cv::Mat m_imageFromFile; //!< original image not resized not overlaid by text
cv::Mat m_imageOriginal; //!< original not resized image
cv::Mat m_image; //!< resized image for transmission at given rate cv::Mat m_image; //!< resized image for transmission at given rate
bool m_imageOK; bool m_imageOK;
@ -474,6 +517,9 @@ private:
std::vector<ATVCamera> m_cameras; //!< vector of available cameras std::vector<ATVCamera> m_cameras; //!< vector of available cameras
int m_cameraIndex; //!< curent camera index in list of available cameras int m_cameraIndex; //!< curent camera index in list of available cameras
std::string m_overlayText;
bool m_showOverlayText;
static const float m_blackLevel; static const float m_blackLevel;
static const float m_spanLevel; static const float m_spanLevel;
static const int m_levelNbSamples; static const int m_levelNbSamples;
@ -496,6 +542,7 @@ private:
void calculateCamerasSizes(); void calculateCamerasSizes();
void resizeCameras(); void resizeCameras();
void resizeCamera(); void resizeCamera();
void mixImageAndText(cv::Mat& image);
inline void pullImageLine(Real& sample) inline void pullImageLine(Real& sample)
{ {

View File

@ -324,6 +324,18 @@ void ATVModGUI::on_camSelect_currentIndexChanged(int index)
m_atvMod->getInputMessageQueue()->push(message); m_atvMod->getInputMessageQueue()->push(message);
} }
void ATVModGUI::on_overlayTextShow_toggled(bool checked)
{
ATVMod::MsgConfigureShowOverlayText* message = ATVMod::MsgConfigureShowOverlayText::create(checked);
m_atvMod->getInputMessageQueue()->push(message);
}
void ATVModGUI::on_overlayText_textEdited(const QString& arg1)
{
ATVMod::MsgConfigureOverlayText* message = ATVMod::MsgConfigureOverlayText::create(ui->overlayText->text());
m_atvMod->getInputMessageQueue()->push(message);
}
void ATVModGUI::configureImageFileName() void ATVModGUI::configureImageFileName()
{ {
qDebug() << "ATVModGUI::configureImageFileName: " << m_imageFileName.toStdString().c_str(); qDebug() << "ATVModGUI::configureImageFileName: " << m_imageFileName.toStdString().c_str();

View File

@ -77,6 +77,9 @@ private slots:
void on_playCamera_toggled(bool checked); void on_playCamera_toggled(bool checked);
void on_camSelect_currentIndexChanged(int index); void on_camSelect_currentIndexChanged(int index);
void on_overlayTextShow_toggled(bool checked);
void on_overlayText_textEdited(const QString& arg1);
void onWidgetRolled(QWidget* widget, bool rollDown); void onWidgetRolled(QWidget* widget, bool rollDown);
void onMenuDoubleClicked(); void onMenuDoubleClicked();

View File

@ -6,7 +6,7 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>386</width> <width>491</width>
<height>364</height> <height>364</height>
</rect> </rect>
</property> </property>
@ -39,7 +39,7 @@
<rect> <rect>
<x>10</x> <x>10</x>
<y>10</y> <y>10</y>
<width>360</width> <width>461</width>
<height>341</height> <height>341</height>
</rect> </rect>
</property> </property>
@ -421,6 +421,50 @@
</property> </property>
</widget> </widget>
</item> </item>
<item>
<widget class="ButtonSwitch" name="overlayTextShow">
<property name="minimumSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
<property name="toolTip">
<string>Activate text overlay</string>
</property>
<property name="text">
<string>T</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="overlayText">
<property name="minimumSize">
<size>
<width>110</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>110</width>
<height>16777215</height>
</size>
</property>
<property name="toolTip">
<string>Text overlay</string>
</property>
<property name="text">
<string/>
</property>
<property name="maxLength">
<number>12</number>
</property>
<property name="cursorPosition">
<number>0</number>
</property>
</widget>
</item>
<item> <item>
<spacer name="horizontalSpacer_3"> <spacer name="horizontalSpacer_3">
<property name="orientation"> <property name="orientation">