Auto crop specific part of an image

时间:2017-04-10 01:57:55

标签: c++ opencv

First and foremost I'd like to stress I'm new to opencv.

I have this image of an electric meter such as this:

And I would like to process the image and just get this:

From what my lecturer has told us, we'll first need to find the contour and then process the image by just getting the rectangle part of the image.

Not sure if this is relevant, I'm using opencv 2.4.13

This is the code based on the tutorial for finding the contour

#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h>
#include <stdlib.h>

using namespace cv;
using namespace std;

Mat src; Mat src_gray;
int thresh = 100;
int max_thresh = 255;
RNG rng(12345);

/// Function header
void thresh_callback(int, void* );

/** @function main */
int main( int argc, char** argv )
{
  /// Load source image and convert it to gray
  src = imread( argv[1], 1 );

  /// Convert image to gray and blur it
  cvtColor( src, src_gray, CV_BGR2GRAY );
  blur( src_gray, src_gray, Size(3,3) );

  /// Create Window
  char* source_window = "Source";
  namedWindow( source_window, CV_WINDOW_AUTOSIZE );
  imshow( source_window, src );

  createTrackbar( " Canny thresh:", "Source", &thresh, max_thresh, thresh_callback );
  thresh_callback( 0, 0 );

  waitKey(0);
  return(0);
}

/** @function thresh_callback */
void thresh_callback(int, void* )
{
  Mat canny_output;
  vector<vector<Point> > contours;
  vector<Vec4i> hierarchy;

  /// Detect edges using canny
  Canny( src_gray, canny_output, thresh, thresh*2, 3 );
  /// Find contours
  findContours( canny_output, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0) );

  /// Draw contours
  Mat drawing = Mat::zeros( canny_output.size(), CV_8UC3 );
  for( int i = 0; i< contours.size(); i++ )
     {
       Scalar color = Scalar( rng.uniform(0, 255), rng.uniform(0,255), rng.uniform(0,255) );
       drawContours( drawing, contours, i, color, 2, 8, hierarchy, 0, Point() );
     }

  /// Show in a window
  namedWindow( "Contours", CV_WINDOW_AUTOSIZE );
  imshow( "Contours", drawing );
}

1 个答案:

答案 0 :(得分:3)

您应该执行以下步骤:

  1. 在恒温器上本地化LCD - 这可以通过边缘检测完成,因为塑料外壳和LCD之间有足够的对比度。

  2. 提取LCD - 给定输入边缘图,您可以找到轮廓并查找矩形的轮廓 - 最大的矩形区域应与LCD对应。 perspective transform可以很好地提取液晶显示屏。

  3. 示例 :(在python中) example.jpg

    # load the example image
    image = cv2.imread("example.jpg)
    
    # pre-process the image by resizing it, converting it to gray scale,blurring it and computing an edge map
    image = imutils.resize(image, height = 500)
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # OpenCV loads RGB as BGR
    blurred = cv2.GaussianBlur(gray, (5, 5), 0) # Essentially reduces high frequency noise try with/without for your case
    edged = cv2.Canny(blurred, 50, 200, 255);
    

    Edge map

    # Extracting LCD here
    # find contours in the edge map, then sort them by their size in descending order
    cnts = cv2.findContours(edged.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    cnts = cnts[0] if imutils.is_cv2() else cnts[1]
    cnts = sorted(cnts, key=cv2.contourArea, reverse=True) # you can sort contours in C++ using implementation for std::vector
    displayCnt = None
    
    # loop over the contours
    for c in cnts:
       # approximate the contour
       peri = cv2.arcLength(c, True)
       approx = cv2.approxPolyDP(c, 0.02 * peri, True)
    
       # if the contour has four vertices, then we have found the thermostat display
       if len(approx) == 4:
           displayCnt = approx.
           break
    
    # extract the thermostat display, apply a perspective transform to it
    warped = four_point_transform(gray, displayCnt.reshape(4, 2))
    output = four_point_transform(image, displayCnt.reshape(4, 2))
    

    Warped Image

    函数four_point_transformhere

    您可能需要根据图像和所获得的内容对代码进行一些调整。我会把它留给你。