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 );
}
答案 0 :(得分:3)
您应该执行以下步骤:
在恒温器上本地化LCD - 这可以通过边缘检测完成,因为塑料外壳和LCD之间有足够的对比度。
提取LCD - 给定输入边缘图,您可以找到轮廓并查找矩形的轮廓 - 最大的矩形区域应与LCD对应。 perspective transform可以很好地提取液晶显示屏。
# 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);
# 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))
函数four_point_transform
为here。
您可能需要根据图像和所获得的内容对代码进行一些调整。我会把它留给你。