-
Notifications
You must be signed in to change notification settings - Fork 60
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[rostwitter] Support extracting base64 images and tweet them from text. #375
Closed
Closed
Changes from all commits
Commits
Show all changes
21 commits
Select commit
Hold shift + click to select a range
b6a7be9
[rostwitter] Enable to tweet with 280(hankaku) characters
iory cfa0ff7
[rostwitter] Fixed encoding for python2
iory 3bc02a7
[rostwitter] Changed so that strings longer than 140 characters are d…
iory ea3fbe7
[rostwitter] Remove _check_and_split_word function
iory a707445
[rostwitter] Add cv_utils to encode/decode image and extract images f…
iory 5519101
[rostwitter] Use SafeLoader for yaml.load
iory 6c33442
[rostwitter] Support extracting base64 images and tweet them from text.
iory 3efafa2
[rostwitter] Delete StringIO. StringIO eliminates newline \n
iory 714631b
[rostwitter] Separate tweets by image.
iory 206cb38
[rostwitter] import izip_longest for python2 compatibility
iory 77d692d
[rostwitter] Fixed input is text only case
iory d4d1b53
[rostwitter] Add launch file
iory e9c6016
[rostwitter] Add README
iory 3d23437
[rostwitter] Assume base64 images are not contiguous without spaces
iory 0be3862
[rostwitter] Add document for base64 image
iory ac921e9
[rostwitter] Add status_code to check error
iory 71d5173
[rostwitter] Avoid error when tweet post returning error code
iory 348eddf
[rostwitter] Add error_code to check error (#6)
nakane11 8e0d3a7
[rostwitter] Fix _check_post_request (#7)
nakane11 2209d73
Merge branch 'master' into twitter-with-base64-images
knorth55 e70df8f
Merge branch 'master' into twitter-with-base64-images
knorth55 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
# rostwitter | ||
|
||
This package is a ROS wrapper for Twitter. You can tweet via ROS. | ||
|
||
# How to use | ||
|
||
## Get access key for API. | ||
|
||
Please get access to the Twitter API. Please refer to the following URL. | ||
|
||
https://developer.twitter.com/en/docs/twitter-api/getting-started/getting-access-to-the-twitter-api | ||
|
||
After that, save the yaml file in the following format. | ||
|
||
``` | ||
CKEY: <Your Consumer API Key> | ||
CSECRET: <Your Consumer SECRET API Key> | ||
AKEY: <Your API Key> | ||
ASECRET: <Your API Secret Key> | ||
``` | ||
|
||
## Launch tweet node | ||
|
||
``` | ||
roslaunch rostwitter tweet.launch account_info:=<PATH TO YOUR YAML FILE> | ||
``` | ||
|
||
## Tweet text | ||
|
||
You can tweet by simply publish on the `/tweet` topic. | ||
|
||
``` | ||
rostopic pub /tweet std_msgs/String "Hello. Tweet via rostwitter (https://github.com/jsk-ros-pkg/jsk_3rdparty)" | ||
``` | ||
|
||
![](./doc/tweet-string.jpg) | ||
|
||
If the string to be tweeted exceeds 140 full-width characters or 280 half-width characters, it will be tweeted in the "thread" display. | ||
|
||
``` | ||
rostopic pub /tweet std_msgs/String """The Zen of Python, by Tim Peters | ||
|
||
Beautiful is better than ugly. | ||
Explicit is better than implicit. | ||
Simple is better than complex. | ||
Complex is better than complicated. | ||
Flat is better than nested. | ||
Sparse is better than dense. | ||
Readability counts. | ||
Special cases aren't special enough to break the rules. | ||
Although practicality beats purity. | ||
Errors should never pass silently. | ||
Unless explicitly silenced. | ||
In the face of ambiguity, refuse the temptation to guess. | ||
There should be one-- and preferably only one --obvious way to do it. | ||
Although that way may not be obvious at first unless you're Dutch. | ||
Now is better than never. | ||
Although never is often better than *right* now. | ||
If the implementation is hard to explain, it's a bad idea. | ||
If the implementation is easy to explain, it may be a good idea. | ||
Namespaces are one honking great idea -- let's do more of those! | ||
""" | ||
``` | ||
|
||
![](./doc/tweet-string-thread.jpg) | ||
|
||
## Tweet text with image | ||
|
||
You can also tweet along with your images. | ||
|
||
If a base64 or image path is inserted in the text, it will jump to the next reply in that section. | ||
|
||
### Image path | ||
|
||
``` | ||
wget https://github.com/k-okada.png -O /tmp/k-okada.png | ||
rostopic pub /tweet std_msgs/String "/tmp/k-okada.png" | ||
``` | ||
|
||
![](./doc/tweet-image-path.jpg) | ||
|
||
### Base64 | ||
|
||
You can even tweet the image by encoding in base64. The following example is in python. | ||
|
||
Do not concatenate multiple base64 images without spaces. | ||
|
||
|
||
```python | ||
import rospy | ||
import cv2 | ||
import std_msgs.msg | ||
import numpy as np | ||
import matplotlib.cm | ||
|
||
from rostwitter.cv_util import extract_media_from_text | ||
from rostwitter.cv_util import encode_image_cv2 | ||
|
||
rospy.init_node('rostwitter_sample') | ||
pub = rospy.Publisher('/tweet', std_msgs.msg.String, queue_size=1) | ||
rospy.sleep(3.0) | ||
|
||
colormap = matplotlib.cm.get_cmap('hsv') | ||
|
||
text = 'Tweet with images. (https://github.com/jsk-ros-pkg/jsk_3rdparty/pull/375)\n' | ||
N = 12 | ||
for i in range(N): | ||
text += str(i) | ||
color = colormap(1.0 * i / N)[:3] | ||
img = color * np.ones((10, 10, 3), dtype=np.uint8) * 255 | ||
img = np.array(img, dtype=np.uint8) | ||
text += encode_image_cv2(img) + ' ' | ||
pub.publish(text) | ||
``` | ||
|
||
[The result of the tweet.](https://twitter.com/pr2jsk/status/1561995909524705280) |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
<launch> | ||
|
||
<arg name="account_info" /> | ||
<arg name="output" default="screen"/> | ||
|
||
<param name="account_info" value="$(arg account_info)" /> | ||
<node name="tweet" | ||
pkg="rostwitter" type="tweet.py" | ||
output="$(arg output)" respawn="true" > | ||
</node> | ||
|
||
</launch> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
import base64 | ||
import imghdr | ||
import os.path | ||
import re | ||
|
||
import cv2 | ||
import numpy as np | ||
import rospy | ||
|
||
|
||
base64_and_filepath_image_pattern = re.compile(r'((?:/9j/)(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)? ?|/\S+\.(?:jpeg|jpg|png|gif))') | ||
|
||
|
||
def encode_image_cv2(img, quality=90): | ||
encode_param = [int(cv2.IMWRITE_JPEG_QUALITY), quality] | ||
result, encimg = cv2.imencode('.jpg', img, encode_param) | ||
b64encoded = base64.b64encode(encimg).decode('ascii') | ||
return b64encoded | ||
|
||
|
||
def decode_image_cv2(b64encoded): | ||
bin = b64encoded.split(",")[-1] | ||
bin = base64.b64decode(bin) | ||
bin = np.frombuffer(bin, np.uint8) | ||
img = cv2.imdecode(bin, cv2.IMREAD_COLOR) | ||
return img | ||
|
||
|
||
def is_base64_image(b64encoded): | ||
try: | ||
decode_image_cv2(b64encoded) | ||
except Exception as e: | ||
rospy.logerr(str(e)) | ||
return False | ||
return True | ||
|
||
|
||
def get_image_from_text(text): | ||
if base64_and_filepath_image_pattern.match(text) is None: | ||
return None | ||
|
||
if os.path.exists(text): | ||
path = text | ||
if imghdr.what(path) in ['jpeg', 'png', 'gif']: | ||
with open(path, 'rb') as f: | ||
return f.read() | ||
else: | ||
succ = is_base64_image(text) | ||
if succ: | ||
bin = text.split(",")[-1] | ||
bin = base64.b64decode(bin) | ||
bin = np.frombuffer(bin, np.uint8) | ||
return bin | ||
|
||
|
||
def extract_media_from_text(text): | ||
texts = base64_and_filepath_image_pattern.split(text) | ||
target_texts = list(filter(lambda x: x is not None and len(x.strip()) > 0, texts)) | ||
|
||
split_texts = [''] | ||
imgs_list = [] | ||
|
||
texts = [] | ||
imgs = [] | ||
for text in target_texts: | ||
img = get_image_from_text(text) | ||
if img is None: | ||
split_texts.append(text) | ||
imgs_list.append(imgs) | ||
imgs = [] | ||
else: | ||
imgs.append(img) | ||
|
||
if len(imgs) > 0: | ||
imgs_list.append(imgs) | ||
if len(split_texts) > 0: | ||
if len(split_texts[0]) == 0 and len(imgs_list[0]) == 0: | ||
split_texts = split_texts[1:] | ||
imgs_list = imgs_list[1:] | ||
return imgs_list, split_texts |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
in order to post
numpy array
data, we need to upgraderequests
python module to2.19.0
and above.psf/requests@8546a15