如何根据可能检测到的结果或情绪添加图像
How to add image depending on what result or emotion it might detect
我一整天都在想办法解决这个问题,因为我想根据可能检测到的情绪结果添加一张图片。只是想添加一些图像,但我对此还是陌生的。谁能帮我解决这个问题。
顺便说一句,这是我的代码:
public class DetectionActivity extends AppCompatActivity {
// Background task of face detection.
private class DetectionTask extends AsyncTask<InputStream, String, Face[]> {
private boolean mSucceed = true;
@Override
protected Face[] doInBackground(InputStream... params) {
// Get an instance of face service client to detect faces in image.
FaceServiceClient faceServiceClient = SampleApp.getFaceServiceClient();
try {
publishProgress("Detecting...");
// Start detection.
return faceServiceClient.detect(
params[0], /* Input stream of image to detect */
true, /* Whether to return face ID */
true, /* Whether to return face landmarks */
new FaceServiceClient.FaceAttributeType[]{
FaceServiceClient.FaceAttributeType.Emotion,
});
} catch (Exception e) {
mSucceed = false;
publishProgress(e.getMessage());
addLog(e.getMessage());
return null;
}
}
@Override
protected void onPreExecute() {
mProgressDialog.show();
addLog("Request: Detecting in image " + mImageUri);
}
@Override
protected void onProgressUpdate(String... progress) {
mProgressDialog.setMessage(progress[0]);
setInfo(progress[0]);
}
@Override
protected void onPostExecute(Face[] result) {
if (mSucceed) {
addLog("Response: Success. Detected " + (result == null ? 0 : result.length)
+ " face(s) in " + mImageUri);
}
// Show the result on screen when detection is done.
setUiAfterDetection(result, mSucceed);
}
}
// Flag to indicate which task is to be performed.
private static final int REQUEST_SELECT_IMAGE = 0;
// The URI of the image selected to detect.
private Uri mImageUri;
// The image selected to detect.
private Bitmap mBitmap;
// Progress dialog popped up when communicating with server.
ProgressDialog mProgressDialog;
// When the activity is created, set all the member variables to initial state.
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_detection);
//this hides the back button and I thank you
getSupportActionBar().setDisplayHomeAsUpEnabled(false);
mProgressDialog = new ProgressDialog(this);
mProgressDialog.setTitle(getString(R.string.progress_dialog_title));
// Disable button "detect" as the image to detect is not selected.
setDetectButtonEnabledStatus(false);
LogHelper.clearDetectionLog();
}
// Save the activity state when it's going to stop.
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putParcelable("ImageUri", mImageUri);
}
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater menuInflater = getMenuInflater();
menuInflater.inflate(R.menu.menu, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch(item.getItemId()){
case R.id.menuAbout:
// Toast.makeText(this, "You clicked about", Toast.LENGTH_SHORT).show();
View messageView = getLayoutInflater().inflate(R.layout.about, null, false);
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setIcon(R.drawable.smile);
builder.setTitle(R.string.app_name);
builder.setView(messageView);
builder.create();
builder.show();
break;
case R.id.menuHelp:
// Toast.makeText(this, "You clicked settings", Toast.LENGTH_SHORT).show();
// Intent help = new Intent(this, HelpActivity.class);
//startActivity(help);
// break;
View messageViewh = getLayoutInflater().inflate(R.layout.help, null, false);
AlertDialog.Builder builderh = new AlertDialog.Builder(this);
builderh.setIcon(R.drawable.smile);
builderh.setTitle(R.string.app_nameh);
builderh.setView(messageViewh);
builderh.create();
builderh.show();
break;
}
return true;
}
// Recover the saved state when the activity is recreated.
@Override
protected void onRestoreInstanceState(@NonNull Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
mImageUri = savedInstanceState.getParcelable("ImageUri");
if (mImageUri != null) {
mBitmap = ImageHelper.loadSizeLimitedBitmapFromUri(
mImageUri, getContentResolver());
}
}
// Called when image selection is done.
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case REQUEST_SELECT_IMAGE:
if (resultCode == RESULT_OK) {
// If image is selected successfully, set the image URI and bitmap.
mImageUri = data.getData();
mBitmap = ImageHelper.loadSizeLimitedBitmapFromUri(
mImageUri, getContentResolver());
if (mBitmap != null) {
// Show the image on screen.
ImageView imageView = (ImageView) findViewById(R.id.image);
imageView.setImageBitmap(mBitmap);
// Add detection log.
addLog("Image: " + mImageUri + " resized to " + mBitmap.getWidth()
+ "x" + mBitmap.getHeight());
}
// Clear the detection result.
FaceListAdapter faceListAdapter = new FaceListAdapter(null);
ListView listView = (ListView) findViewById(R.id.list_detected_faces);
listView.setAdapter(faceListAdapter);
// Clear the information panel.
setInfo("");
// Enable button "detect" as the image is selected and not detected.
setDetectButtonEnabledStatus(true);
}
break;
default:
break;
}
}
// Called when the "Select Image" button is clicked.
public void selectImage(View view) {
Intent intent = new Intent(this, SelectImageActivity.class);
startActivityForResult(intent, REQUEST_SELECT_IMAGE);
}
// Called when the "Detect" button is clicked.
public void detect(View view) {
// Put the image into an input stream for detection.
ByteArrayOutputStream output = new ByteArrayOutputStream();
mBitmap.compress(Bitmap.CompressFormat.JPEG, 100, output);
ByteArrayInputStream inputStream = new ByteArrayInputStream(output.toByteArray());
// Start a background task to detect faces in the image.
new DetectionTask().execute(inputStream);
// Prevent button click during detecting.
setAllButtonsEnabledStatus(false);
}
// View the log of service calls.
public void viewLog(View view) {
Intent intent = new Intent(this, DetectionLogActivity.class);
startActivity(intent);
}
// Show the result on screen when detection is done.
private void setUiAfterDetection(Face[] result, boolean succeed) {
// Detection is done, hide the progress dialog.
mProgressDialog.dismiss();
// Enable all the buttons.
setAllButtonsEnabledStatus(true);
// Disable button "detect" as the image has already been detected.
setDetectButtonEnabledStatus(false);
if (succeed) {
// The information about the detection result.
String detectionResult;
if (result != null) {
detectionResult = result.length + " face"
+ (result.length != 1 ? "s" : "") + " detected";
// Show the detected faces on original image.
ImageView imageView = (ImageView) findViewById(R.id.image);
imageView.setImageBitmap(ImageHelper.drawFaceRectanglesOnBitmap(
mBitmap, result, true));
// Set the adapter of the ListView which contains the details of the detected faces.
FaceListAdapter faceListAdapter = new FaceListAdapter(result);
// Show the detailed list of detected faces.
ListView listView = (ListView) findViewById(R.id.list_detected_faces);
listView.setAdapter(faceListAdapter);
} else {
detectionResult = "0 face detected";
}
setInfo(detectionResult);
}
mImageUri = null;
mBitmap = null;
}
// Set whether the buttons are enabled.
private void setDetectButtonEnabledStatus(boolean isEnabled) {
Button detectButton = (Button) findViewById(R.id.detect);
detectButton.setEnabled(isEnabled);
}
// Set whether the buttons are enabled.
private void setAllButtonsEnabledStatus(boolean isEnabled) {
Button selectImageButton = (Button) findViewById(R.id.select_image);
selectImageButton.setEnabled(isEnabled);
Button detectButton = (Button) findViewById(R.id.detect);
detectButton.setEnabled(isEnabled);
// Button ViewLogButton = (Button) findViewById(R.id.view_log);
// ViewLogButton.setEnabled(isEnabled);
}
// Set the information panel on screen.
private void setInfo(String info) {
TextView textView = (TextView) findViewById(R.id.info);
textView.setText(info);
}
// Add a log item.
private void addLog(String log) {
LogHelper.addDetectionLog(log);
}
// The adapter of the GridView which contains the details of the detected faces.
private class FaceListAdapter extends BaseAdapter {
// The detected faces.
List<Face> faces;
// The thumbnails of detected faces.
List<Bitmap> faceThumbnails;
// Initialize with detection result.
FaceListAdapter(Face[] detectionResult) {
faces = new ArrayList<>();
faceThumbnails = new ArrayList<>();
if (detectionResult != null) {
faces = Arrays.asList(detectionResult);
for (Face face : faces) {
try {
// Crop face thumbnail with five main landmarks drawn from original image.
faceThumbnails.add(ImageHelper.generateFaceThumbnail(
mBitmap, face.faceRectangle));
} catch (IOException e) {
// Show the exception when generating face thumbnail fails.
setInfo(e.getMessage());
}
}
}
}
@Override
public boolean isEnabled(int position) {
return false;
}
@Override
public int getCount() {
return faces.size();
}
@Override
public Object getItem(int position) {
return faces.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
if (convertView == null) {
LayoutInflater layoutInflater =
(LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = layoutInflater.inflate(R.layout.item_face_with_description, parent, false);
}
convertView.setId(position);
// Show the face thumbnail.
((ImageView) convertView.findViewById(R.id.face_thumbnail)).setImageBitmap(
faceThumbnails.get(position));
// Show the face details.
String getEmotion;
// String improve = improveMessage(getEmotion);
DecimalFormat formatter = new DecimalFormat("#0.0");
//add
// String message = findMessage(getEmotion());
// String improve = improveMessage(getEmotion);
String face_description = String.format("Emotion: %s\n",
getEmotion(faces.get(position).faceAttributes.emotion)
);
((TextView) convertView.findViewById(R.id.text_detected_face)).setText(face_description);
return convertView;
}
private String getEmotion(Emotion emotion) {
String emotionType = "";
double emotionValue = 0.0;
String emotionInfo = "";
if (emotion.anger > emotionValue) {
emotionValue = emotion.anger;
emotionType = "Anger";
emotionInfo = "If you haven't fed him/her yet maybe this precious one is thirsty or hungry.\n Try giving your attention. If your baby is acting unusual it's best to seek for medical help.";
}
if (emotion.contempt > emotionValue) {
emotionValue = emotion.contempt;
emotionType = "Contempt";
emotionInfo = "You go girl!";
}
if (emotion.disgust > emotionValue) {
emotionValue = emotion.disgust;
emotionType = "Disgust";
emotionInfo = "Look! If your baby is feeling this way mabye she/he doesn't like this. \n If what your doing right now is good for him/her maybe you can support that.";
}
if (emotion.fear > emotionValue) {
emotionValue = emotion.fear;
emotionType = "Fear";
emotionInfo = "Your baby looks somewhat uncomfortable.\n Make your baby feel comfortable and take note of what makes them feel like that. ";
}
if (emotion.happiness > emotionValue) {
emotionValue = emotion.happiness;
emotionType = "Happiness";
emotionInfo = "Just continue what you are doing. It is important to remember what can make them happy. \n";
}
if (emotion.neutral > emotionValue) {
emotionValue = emotion.neutral;
emotionType = "Neutral";
emotionInfo = "Maybe you should just observe first";
}
if (emotion.sadness > emotionValue) {
emotionValue = emotion.sadness;
emotionType = "Sadness";
emotionInfo = "Just cuddle or dandle your baby.";
}
if (emotion.surprise > emotionValue) {
emotionValue = emotion.surprise;
emotionType = "Surprise";
emotionInfo = "Oooh look. Play with your baby. Try doing peek a boo";
}
return String.format("%s: %f \n\n%s", emotionType, emotionValue, emotionInfo);
}
}
}
如果检测到的情绪是快乐的,我只想添加一些图像。请帮帮我。非常感谢任何帮助。谢谢:)
我想在 emotionInfo 之后添加。
我猜detectWithStream
是你想要的。
官方文档:Faces.detectWithStream Method
来自 Java SDK,如果成功,List<DetectedFace>
对象将 return。
我一整天都在想办法解决这个问题,因为我想根据可能检测到的情绪结果添加一张图片。只是想添加一些图像,但我对此还是陌生的。谁能帮我解决这个问题。
顺便说一句,这是我的代码:
public class DetectionActivity extends AppCompatActivity {
// Background task of face detection.
private class DetectionTask extends AsyncTask<InputStream, String, Face[]> {
private boolean mSucceed = true;
@Override
protected Face[] doInBackground(InputStream... params) {
// Get an instance of face service client to detect faces in image.
FaceServiceClient faceServiceClient = SampleApp.getFaceServiceClient();
try {
publishProgress("Detecting...");
// Start detection.
return faceServiceClient.detect(
params[0], /* Input stream of image to detect */
true, /* Whether to return face ID */
true, /* Whether to return face landmarks */
new FaceServiceClient.FaceAttributeType[]{
FaceServiceClient.FaceAttributeType.Emotion,
});
} catch (Exception e) {
mSucceed = false;
publishProgress(e.getMessage());
addLog(e.getMessage());
return null;
}
}
@Override
protected void onPreExecute() {
mProgressDialog.show();
addLog("Request: Detecting in image " + mImageUri);
}
@Override
protected void onProgressUpdate(String... progress) {
mProgressDialog.setMessage(progress[0]);
setInfo(progress[0]);
}
@Override
protected void onPostExecute(Face[] result) {
if (mSucceed) {
addLog("Response: Success. Detected " + (result == null ? 0 : result.length)
+ " face(s) in " + mImageUri);
}
// Show the result on screen when detection is done.
setUiAfterDetection(result, mSucceed);
}
}
// Flag to indicate which task is to be performed.
private static final int REQUEST_SELECT_IMAGE = 0;
// The URI of the image selected to detect.
private Uri mImageUri;
// The image selected to detect.
private Bitmap mBitmap;
// Progress dialog popped up when communicating with server.
ProgressDialog mProgressDialog;
// When the activity is created, set all the member variables to initial state.
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_detection);
//this hides the back button and I thank you
getSupportActionBar().setDisplayHomeAsUpEnabled(false);
mProgressDialog = new ProgressDialog(this);
mProgressDialog.setTitle(getString(R.string.progress_dialog_title));
// Disable button "detect" as the image to detect is not selected.
setDetectButtonEnabledStatus(false);
LogHelper.clearDetectionLog();
}
// Save the activity state when it's going to stop.
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putParcelable("ImageUri", mImageUri);
}
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater menuInflater = getMenuInflater();
menuInflater.inflate(R.menu.menu, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch(item.getItemId()){
case R.id.menuAbout:
// Toast.makeText(this, "You clicked about", Toast.LENGTH_SHORT).show();
View messageView = getLayoutInflater().inflate(R.layout.about, null, false);
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setIcon(R.drawable.smile);
builder.setTitle(R.string.app_name);
builder.setView(messageView);
builder.create();
builder.show();
break;
case R.id.menuHelp:
// Toast.makeText(this, "You clicked settings", Toast.LENGTH_SHORT).show();
// Intent help = new Intent(this, HelpActivity.class);
//startActivity(help);
// break;
View messageViewh = getLayoutInflater().inflate(R.layout.help, null, false);
AlertDialog.Builder builderh = new AlertDialog.Builder(this);
builderh.setIcon(R.drawable.smile);
builderh.setTitle(R.string.app_nameh);
builderh.setView(messageViewh);
builderh.create();
builderh.show();
break;
}
return true;
}
// Recover the saved state when the activity is recreated.
@Override
protected void onRestoreInstanceState(@NonNull Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
mImageUri = savedInstanceState.getParcelable("ImageUri");
if (mImageUri != null) {
mBitmap = ImageHelper.loadSizeLimitedBitmapFromUri(
mImageUri, getContentResolver());
}
}
// Called when image selection is done.
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case REQUEST_SELECT_IMAGE:
if (resultCode == RESULT_OK) {
// If image is selected successfully, set the image URI and bitmap.
mImageUri = data.getData();
mBitmap = ImageHelper.loadSizeLimitedBitmapFromUri(
mImageUri, getContentResolver());
if (mBitmap != null) {
// Show the image on screen.
ImageView imageView = (ImageView) findViewById(R.id.image);
imageView.setImageBitmap(mBitmap);
// Add detection log.
addLog("Image: " + mImageUri + " resized to " + mBitmap.getWidth()
+ "x" + mBitmap.getHeight());
}
// Clear the detection result.
FaceListAdapter faceListAdapter = new FaceListAdapter(null);
ListView listView = (ListView) findViewById(R.id.list_detected_faces);
listView.setAdapter(faceListAdapter);
// Clear the information panel.
setInfo("");
// Enable button "detect" as the image is selected and not detected.
setDetectButtonEnabledStatus(true);
}
break;
default:
break;
}
}
// Called when the "Select Image" button is clicked.
public void selectImage(View view) {
Intent intent = new Intent(this, SelectImageActivity.class);
startActivityForResult(intent, REQUEST_SELECT_IMAGE);
}
// Called when the "Detect" button is clicked.
public void detect(View view) {
// Put the image into an input stream for detection.
ByteArrayOutputStream output = new ByteArrayOutputStream();
mBitmap.compress(Bitmap.CompressFormat.JPEG, 100, output);
ByteArrayInputStream inputStream = new ByteArrayInputStream(output.toByteArray());
// Start a background task to detect faces in the image.
new DetectionTask().execute(inputStream);
// Prevent button click during detecting.
setAllButtonsEnabledStatus(false);
}
// View the log of service calls.
public void viewLog(View view) {
Intent intent = new Intent(this, DetectionLogActivity.class);
startActivity(intent);
}
// Show the result on screen when detection is done.
private void setUiAfterDetection(Face[] result, boolean succeed) {
// Detection is done, hide the progress dialog.
mProgressDialog.dismiss();
// Enable all the buttons.
setAllButtonsEnabledStatus(true);
// Disable button "detect" as the image has already been detected.
setDetectButtonEnabledStatus(false);
if (succeed) {
// The information about the detection result.
String detectionResult;
if (result != null) {
detectionResult = result.length + " face"
+ (result.length != 1 ? "s" : "") + " detected";
// Show the detected faces on original image.
ImageView imageView = (ImageView) findViewById(R.id.image);
imageView.setImageBitmap(ImageHelper.drawFaceRectanglesOnBitmap(
mBitmap, result, true));
// Set the adapter of the ListView which contains the details of the detected faces.
FaceListAdapter faceListAdapter = new FaceListAdapter(result);
// Show the detailed list of detected faces.
ListView listView = (ListView) findViewById(R.id.list_detected_faces);
listView.setAdapter(faceListAdapter);
} else {
detectionResult = "0 face detected";
}
setInfo(detectionResult);
}
mImageUri = null;
mBitmap = null;
}
// Set whether the buttons are enabled.
private void setDetectButtonEnabledStatus(boolean isEnabled) {
Button detectButton = (Button) findViewById(R.id.detect);
detectButton.setEnabled(isEnabled);
}
// Set whether the buttons are enabled.
private void setAllButtonsEnabledStatus(boolean isEnabled) {
Button selectImageButton = (Button) findViewById(R.id.select_image);
selectImageButton.setEnabled(isEnabled);
Button detectButton = (Button) findViewById(R.id.detect);
detectButton.setEnabled(isEnabled);
// Button ViewLogButton = (Button) findViewById(R.id.view_log);
// ViewLogButton.setEnabled(isEnabled);
}
// Set the information panel on screen.
private void setInfo(String info) {
TextView textView = (TextView) findViewById(R.id.info);
textView.setText(info);
}
// Add a log item.
private void addLog(String log) {
LogHelper.addDetectionLog(log);
}
// The adapter of the GridView which contains the details of the detected faces.
private class FaceListAdapter extends BaseAdapter {
// The detected faces.
List<Face> faces;
// The thumbnails of detected faces.
List<Bitmap> faceThumbnails;
// Initialize with detection result.
FaceListAdapter(Face[] detectionResult) {
faces = new ArrayList<>();
faceThumbnails = new ArrayList<>();
if (detectionResult != null) {
faces = Arrays.asList(detectionResult);
for (Face face : faces) {
try {
// Crop face thumbnail with five main landmarks drawn from original image.
faceThumbnails.add(ImageHelper.generateFaceThumbnail(
mBitmap, face.faceRectangle));
} catch (IOException e) {
// Show the exception when generating face thumbnail fails.
setInfo(e.getMessage());
}
}
}
}
@Override
public boolean isEnabled(int position) {
return false;
}
@Override
public int getCount() {
return faces.size();
}
@Override
public Object getItem(int position) {
return faces.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
if (convertView == null) {
LayoutInflater layoutInflater =
(LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = layoutInflater.inflate(R.layout.item_face_with_description, parent, false);
}
convertView.setId(position);
// Show the face thumbnail.
((ImageView) convertView.findViewById(R.id.face_thumbnail)).setImageBitmap(
faceThumbnails.get(position));
// Show the face details.
String getEmotion;
// String improve = improveMessage(getEmotion);
DecimalFormat formatter = new DecimalFormat("#0.0");
//add
// String message = findMessage(getEmotion());
// String improve = improveMessage(getEmotion);
String face_description = String.format("Emotion: %s\n",
getEmotion(faces.get(position).faceAttributes.emotion)
);
((TextView) convertView.findViewById(R.id.text_detected_face)).setText(face_description);
return convertView;
}
private String getEmotion(Emotion emotion) {
String emotionType = "";
double emotionValue = 0.0;
String emotionInfo = "";
if (emotion.anger > emotionValue) {
emotionValue = emotion.anger;
emotionType = "Anger";
emotionInfo = "If you haven't fed him/her yet maybe this precious one is thirsty or hungry.\n Try giving your attention. If your baby is acting unusual it's best to seek for medical help.";
}
if (emotion.contempt > emotionValue) {
emotionValue = emotion.contempt;
emotionType = "Contempt";
emotionInfo = "You go girl!";
}
if (emotion.disgust > emotionValue) {
emotionValue = emotion.disgust;
emotionType = "Disgust";
emotionInfo = "Look! If your baby is feeling this way mabye she/he doesn't like this. \n If what your doing right now is good for him/her maybe you can support that.";
}
if (emotion.fear > emotionValue) {
emotionValue = emotion.fear;
emotionType = "Fear";
emotionInfo = "Your baby looks somewhat uncomfortable.\n Make your baby feel comfortable and take note of what makes them feel like that. ";
}
if (emotion.happiness > emotionValue) {
emotionValue = emotion.happiness;
emotionType = "Happiness";
emotionInfo = "Just continue what you are doing. It is important to remember what can make them happy. \n";
}
if (emotion.neutral > emotionValue) {
emotionValue = emotion.neutral;
emotionType = "Neutral";
emotionInfo = "Maybe you should just observe first";
}
if (emotion.sadness > emotionValue) {
emotionValue = emotion.sadness;
emotionType = "Sadness";
emotionInfo = "Just cuddle or dandle your baby.";
}
if (emotion.surprise > emotionValue) {
emotionValue = emotion.surprise;
emotionType = "Surprise";
emotionInfo = "Oooh look. Play with your baby. Try doing peek a boo";
}
return String.format("%s: %f \n\n%s", emotionType, emotionValue, emotionInfo);
}
}
}
如果检测到的情绪是快乐的,我只想添加一些图像。请帮帮我。非常感谢任何帮助。谢谢:)
我想在 emotionInfo 之后添加。
我猜detectWithStream
是你想要的。
官方文档:Faces.detectWithStream Method
来自 Java SDK,如果成功,List<DetectedFace>
对象将 return。